<p>In Spring Data Solr Repositories article we will discuss about Spring Data repository, Spring Data project provides Spring Data Repository abstraction to reduce the amount of boilerplate code. Earlier there are various persistence stores require lot of code for data access layers implementation. Spring Data repository abstraction almost avoid all code required to implement data access layers.</p>
<p><img class="aligncenter size-full wp-image-4115" src="https://dineshonjava.com/wp-content/uploads/2018/02/spring-data-solr.png" alt="Spring Data Solr Repositories" width="1120" height="628" /></p>
<p>Repository is a central interface of the Spring Data repository abstraction. As you can see in the above diagram, the Spring Data project is not only for a particular technologies such as relational databases it is also for NoSQL databases such as MongoDB, Cassandra, Solr etc. But Repository interface is a central interface for all various technologies. It takes the domain class to manage as well as ID type of the domain class as type arguments.</p>
<div align="center"><iframe style="width: 120px; height: 240px;" src="//ws-in.amazon-adsystem.com/widgets/q?ServiceVersion=20070822&;OneJS=1&;Operation=GetAdHtml&;MarketPlace=IN&;source=ac&;ref=qf_sp_asin_til&;ad_type=product_link&;tracking_id=dineshonjav06-21&;marketplace=amazon&;region=IN&;placement=1788299450&;asins=1788299450&;linkId=05b0146b0a85f4472697901e353dc276&;show_border=true&;link_opens_in_new_window=true&;price_color=333333&;title_color=0066c0&;bg_color=ffffff" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"><br />
</iframe></div>
<p>This Repository interface act as a marker interface but Spring Data provides another interface that extend this Repository interface. The name of this interface is CrudRepository, it provides sophisticated CRUD functionality for the entity class that is being managed. Let&#8217;s see as following:</p>
<pre class="highlight">public interface CrudRepository<;T, ID extends Serializable>; 
extends Repository<;T, ID>; { 
 
<;S extends T>; S save(S entity); 
 
Optional<;T>; findById(ID primaryKey); 
 
Iterable<;T>; findAll(); 
 
long count(); 
 
void delete(T entity); 
 
boolean existsById(ID primaryKey); 
 
//... more functionality omitted. 
} 
</pre>
<p>As you can see the above interface provides several methods, that are required for Data Access layer. As following:</p>
<ul>
<li><em>S save(S entity)</em>&#8211; This method saves the given entity.</li>
<li><em>findById(ID primaryKey)</em>&#8211; This method returns the entity identified by the given ID.</li>
<li><em>findAll()</em>&#8211; This method is responsible for returning all entities.</li>
<li><em>count()</em>&#8211; This method will be used to return the number of entities.</li>
<li><em>delete(T entity)</em>&#8211; This method deletes the given entity.</li>
<li><em>existsById(ID primaryKey)</em>&#8211; It indicates whether an entity with the given ID exists.</li>
</ul>
<p>The Spring Data project also provides support for pagination and sorting. The Spring Data repositories has another repository interface that extends CrudRepository to provide pagination and sorting functionalities, that is PagingAndSortingRepository. It is abstraction that adds additional methods to ease paginated access to entities as following:</p>
<pre class="highlight">public interface PagingAndSortingRepository<;T, ID extends Serializable>; 
extends CrudRepository<;T, ID>; { 
 
Iterable<;T>; findAll(Sort sort); 
 
Page<;T>; findAll(Pageable pageable); 
} 
</pre>
<p>The above interface adds two more methods, <em>findAll(Sort sort)</em> returns sorted entities and <em>findAll(Pageable pageable)</em> returns results into paginated form. Let&#8217;s see how to access the second page of Order by page size of 10 as following:</p>
<pre class="highlight">PagingAndSortingRepository<;User, Long>; repository = //... get access to a bean 
Page<;Order>; orders = repository.findAll(PageRequest.of(1, 10)); 
</pre>
<p>As we have seen that how to access paginated results using the PagingAndSortingRepository interface. Let&#8217;s see the how to create Spring Data Solr repositories.</p>
<h2>Creating Spring Data Solr repositories</h2>
<p>Spring Data project also provides persistence technology-specific abstractions, such as SolrCrudRepository, MongoCrudRepository, JpaCrudRepository etc. These interfaces extend CrudRepository and expose the functionalities of the specific persistence technology.</p>
<p>First, define a domain class-specific repository interface. The interface must extend Repository and be typed to the domain class and an ID type. If you want to expose CRUD methods for that domain type, extend CrudRepository instead of Repository.</p>
<pre class="highlight">package com.doj.app.repository; 
 
import org.springframework.data.domain.Page; 
import org.springframework.data.domain.Pageable; 
import org.springframework.data.solr.repository.Query; 
import org.springframework.data.solr.repository.SolrCrudRepository; 
 
import com.doj.app.pojo.Order; 
 
/** 
* @author Dinesh.Rajput 
* 
*/ 
public interface SolrOrderRepository extends SolrCrudRepository<;Order, Long>; { 
 
Order findByOrderid(Long orderid); 
... 
 
} 
</pre>
<h3>Document Mapping</h3>
<p>In the above repository class, Order is a domain class as following:</p>
<pre class="highlight">/** 
 * 
 */ 
package com.doj.app.pojo; 
 
import org.springframework.data.annotation.Id; 
import org.springframework.data.solr.core.mapping.Indexed; 
import org.springframework.data.solr.core.mapping.SolrDocument; 
 
/** 
 * @author Dinesh.Rajput 
 * 
 */ 
@SolrDocument(collection="Order") 
public class Order { 
 
 @Id 
 @Indexed(name = "oid", type = "long") 
 private Long orderid; 
 
 @Indexed(name = "oname", type = "string") 
 private String orderName; 
 
 @Indexed(name = "odesc", type = "string") 
 private String orderDescription; 
 
 @Indexed(name = "pname", type = "string") 
 private String productName; 
 
 @Indexed(name = "cname", type = "string") 
 private String customerName; 
 
 @Indexed(name = "cmobile", type = "string") 
 private String customerMobile; 
 
	public Long getOrderid() { 
		return orderid; 
	} 
 
	public void setOrderid(Long orderid) { 
		this.orderid = orderid; 
	} 
 
	public String getOrderName() { 
		return orderName; 
	} 
 
	public void setOrderName(String orderName) { 
		this.orderName = orderName; 
	} 
 
	public String getProductName() { 
		return productName; 
	} 
 
	public void setProductName(String productName) { 
		this.productName = productName; 
	} 
 
	public String getCustomerName() { 
		return customerName; 
	} 
 
	public void setCustomerName(String customerName) { 
		this.customerName = customerName; 
	} 
 
	public String getCustomerMobile() { 
		return customerMobile; 
	} 
 
	public void setCustomerMobile(String customerMobile) { 
		this.customerMobile = customerMobile; 
	} 
 
	public String getOrderDescription() { 
		return orderDescription; 
	} 
 
	public void setOrderDescription(String orderDescription) { 
		this.orderDescription = orderDescription; 
	} 
 
} 
</pre>
<p>The above class is domain class for Spring Data Solr repository. Let&#8217;s see in the next section how to configure Solr repository using Spring Namespace.</p>
<h2>Spring Data Solr Namespace</h2>
<p>The Spring Data Solr module contains a custom namespace.</p>
<pre class="highlight"><;?xml version="1.0" encoding="UTF-8"?>; 
<;beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:solr="http://www.springframework.org/schema/data/solr" 
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd 
http://www.springframework.org/schema/data/solr 
http://www.springframework.org/schema/data/solr/spring-solr.xsd">; 
 
<;solr:repositories base-package="com.dineshonjava.repositories" />; 
<;solr:solr-client id="solrClient" url="http://locahost:8983/solr" />; 
 
<;/beans>; 
</pre>
<p>Using the solr-client element registers an instance of SolrClient in the context. Let&#8217;s configure same above configuration using the Annotation based configuration.</p>
<h2>Annotation based configuration</h2>
<p>The Spring Data Solr repositories support cannot only be activated through an XML namespace but also using an annotation through JavaConfig.</p>
<pre class="highlight">@Configuration 
@EnableSolrRepositories 
class ApplicationConfig { 
 
 @Bean 
 public SolrClient solrClient() { 
 EmbeddedSolrServerFactory factory = new EmbeddedSolrServerFactory("classpath:com/dineshonjava/solr"); 
 return factory.getSolrServer(); 
 } 
 
 @Bean 
 public SolrOperations solrTemplate() { 
 return new SolrTemplate(solrClient()); 
 } 
} 
</pre>
<p>In the above configuration, we have enabled Spring Data Solr repository using the <em>@EnableSolrRepositories</em> annotation, which essentially carries the same attributes as the XML namespace does. We can also give <em>basePackage</em> attribute to scan all available repositories.</p>
<p>Let&#8217;s see how to create Query methods in Solr Repository in the next section.</p>
<h2>Query methods in Solr Repository</h2>
<p>The Solr module supports defining a query manually as String or have it being derived from the method name. So deriving the query from the method name is not always sufficient and/or may result in unreadable method names. We can also use the @Query annotation or Solr named queries.</p>
<h3>Query creation from method names</h3>
<pre class="highlight">public interface SolrOrderRepository extends SolrCrudRepository<;Order, Long>; { 
 
List findByOrderidAndOrderName(Long orderid, String orderName); 
} 
</pre>
<p>The method name above will be translated into the following solr query</p>
<pre class="highlight">q=oid:?0 AND oname:?1 
</pre>
<h3>Using @Query Annotation</h3>
<p>You can also bind your own query to query method of the Spring Data Solr repositories using <em>@Query</em> annotation as following:</p>
<pre class="highlight">public interface SolrOrderRepository extends SolrCrudRepository<;Order, Long>; { 
 
... 
 
@Query("odesc:*?0*") 
Page<;Order>; findByOrderDescription(String searchTerm, Pageable pageable); 
 
@Query("odesc:*?0* OR oname:*?0* OR pname:*?0*") 
Page<;Order>; findByCustomerQuery(String searchTerm, Pageable pageable); 
 
} 
</pre>
<h3>Using NamedQueries</h3>
<p>You can also use named queries by declring into properties file in the classpath and load this the properties file at the time configuration for the Spring Data Solr repositories.</p>
<p><strong>Declare named query in properties file</strong></p>
<pre class="highlight">Order.findByNamedQuery=odesc:?0 
Order.findByOrderName=oname:?0 
 
public interface SolrOrderRepository extends SolrCrudRepository<;Order, Long>; { 
 
List<;Order, Long>; findByNamedQuery(String orderDesc); 
 
@Query(name = "Order.findByOrderName") 
List<;Order, Long>; findByAnnotatedNamedQuery(String name); 
 
} 
</pre>
<p>According Spring Document for the Spring Data Solr, following query methods are supported.</p>
<table class="tableblock frame-all grid-all spread">
<caption class="title">Supported keywords inside method names</caption>
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Keyword</th>
<th class="tableblock halign-left valign-top">Sample</th>
<th class="tableblock halign-left valign-top">Solr Query String</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>And</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByNameAndPopularity</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=name:?0 AND popularity:?1</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>Or</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByNameOrPopularity</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=name:?0 OR popularity:?1</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>Is</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByName</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=name:?0</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>Not</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByNameNot</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=-name:?0</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>IsNull</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByNameIsNull</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=-name:[* TO *]</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>IsNotNull</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByNameIsNotNull</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=name:[* TO *]</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>Between</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByPopularityBetween</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=popularity:[?0 TO ?1]</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>LessThan</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByPopularityLessThan</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=popularity:[* TO ?0}</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>LessThanEqual</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByPopularityLessThanEqual</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=popularity:[* TO ?0]</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>GreaterThan</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByPopularityGreaterThan</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=popularity:{?0 TO *]</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>GreaterThanEqual</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByPopularityGreaterThanEqual</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=popularity:[?0 TO *]</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>Before</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByLastModifiedBefore</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=last_modified:[* TO ?0}</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>After</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByLastModifiedAfter</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=last_modified:{?0 TO *]</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>Like</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByNameLike</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=name:?0*</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>NotLike</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByNameNotLike</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=-name:?0*</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>StartingWith</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByNameStartingWith</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=name:?0*</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>EndingWith</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByNameEndingWith</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=name:*?0</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>Containing</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByNameContaining</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=name:*?0*</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>Matches</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByNameMatches</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=name:?0</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>In</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByNameIn(Collection<;String>;<br />
names)</code></td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=name:(?0…​ )</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>NotIn</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByNameNotIn(Collection<;String>;<br />
names)</code></td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=-name:(?0…​ )</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>Within</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByStoreWithin(Point, Distance)</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q={!geofilt pt=?0.latitude,?0.longitude sfield=store<br />
d=?1}</code></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>Near</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByStoreNear(Point, Distance)</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q={!bbox pt=?0.latitude,?0.longitude sfield=store<br />
d=?1}</code></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>Near</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByStoreNear(Box)</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=store[?0.start.latitude,?0.start.longitude TO<br />
?0.end.latitude,?0.end.longitude]</code></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>True</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByAvailableTrue</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=inStock:true</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>False</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByAvailableFalse</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=inStock:false</code></p>
</td>
</tr>
<tr>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>OrderBy</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>findByAvailableTrueOrderByNameDesc</code></p>
</td>
<td class="tableblock halign-left valign-top">
<p class="tableblock"><code>q=inStock:true&;sort=name desc</code></p>
</td>
</tr>
</tbody>
</table>
<div align="center"><iframe style="width: 120px; height: 240px;" src="//ws-in.amazon-adsystem.com/widgets/q?ServiceVersion=20070822&;OneJS=1&;Operation=GetAdHtml&;MarketPlace=IN&;source=ac&;ref=tf_til&;ad_type=product_link&;tracking_id=dineshonjav06-21&;marketplace=amazon&;region=IN&;placement=1787127567&;asins=1787127567&;linkId=a1e64f621b5e6128d8cb10e876eb1c48&;show_border=true&;link_opens_in_new_window=true&;price_color=333333&;title_color=0066c0&;bg_color=ffffff" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" align="center"><span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span><br />
</iframe></div>
<p>Thanks for reading with the Dineshonjava. Let&#8217;s we have lot of articles in the series of the <strong><a href="https://dineshonjava.com/spring-data-solr-tutorial/">Spring Data Solr tutorial</a></strong>.</p>
<p>Happy learning with us!!! :)</p>
<div class="wp-post-navigation"> 
									 <div class="wp-post-navigation-pre"> 
									 <a href="https://dineshonjava.com/spring-data-solr-configuration-using-spring-boot/">Previous</a> 
									 </div> 
									 <div class="wp-post-navigation-next"> 
									 <a href="https://dineshonjava.com/spring-data-solr-dynamic-queries/">Next</a> 
									 </div> 
									</div>
<script type="text/javascript">
jQuery(document).ready(function($) {
 $.post('https://dineshonjava.com/wp-admin/admin-ajax.php', {action: 'mts_view_count', id: '4176'});
});
</script>
Strategy Design Patterns We can easily create a strategy design pattern using lambda. To implement…
Decorator Pattern A decorator pattern allows a user to add new functionality to an existing…
Delegating pattern In software engineering, the delegation pattern is an object-oriented design pattern that allows…
Technology has emerged a lot in the last decade, and now we have artificial intelligence;…
Managing a database is becoming increasingly complex now due to the vast amount of data…
Overview In this article, we will explore Spring Scheduler how we could use it by…