diff --git a/formatting.xml b/formatting.xml
index e69de29bb..b60c70a4e 100644
--- a/formatting.xml
+++ b/formatting.xml
@@ -0,0 +1,820 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 8078f6f96..51d100828 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,131 +1,132 @@
-
- 4.0.0
-
- org.springframework.data
- spring-data-elasticsearch
- 1.0.0.BUILD-SNAPSHOT
-
-
+
+ 4.0.0
+
+ org.springframework.data
+ spring-data-elasticsearch
+ 1.0.0.BUILD-SNAPSHOT
+
+ org.springframework.data.buildspring-data-parent1.1.0.BUILD-SNAPSHOT../spring-data-build/parent/pom.xml
-
- Spring Data Elasticsearch
- Spring Data Implementation for Elasticsearch
- https://github.com/SpringSource/spring-data-elasticsearch
-
-
- DATAES
-
- 3.2.1
- 2.6
- 0.90.0
- 1.9.2
- 1.6.0.BUILD-SNAPSHOT
-
-
+ Spring Data Elasticsearch
+ Spring Data Implementation for Elasticsearch
+ https://github.com/SpringSource/spring-data-elasticsearch
-
-
-
-
- org.springframework
- spring-context
- ${spring}
-
-
- commons-logging
- commons-logging
-
-
-
-
-
- org.springframework
- spring-tx
- ${spring}
-
+
-
-
- cglib
- cglib
- 2.2.2
- test
-
+ DATAES
-
-
- org.springframework.data
- spring-data-commons
- ${springdata.commons}
-
+ 3.2.1
+ 2.6
+ 0.90.0
+ 1.9.2
+ 1.6.0.BUILD-SNAPSHOT
-
-
- commons-lang
- commons-lang
- ${commonslang}
-
-
- commons-collections
- commons-collections
- ${commonscollections}
-
+
-
-
- joda-time
- joda-time
- ${jodatime}
-
+
-
-
- org.elasticsearch
- elasticsearch
- ${elasticsearch}
-
+
+
+ org.springframework
+ spring-context
+ ${spring}
+
+
+ commons-logging
+ commons-logging
+
+
+
-
-
- org.codehaus.jackson
- jackson-mapper-asl
- ${jackson}
-
+
+ org.springframework
+ spring-tx
+ ${spring}
+
-
-
- javax.enterprise
- cdi-api
- ${cdi}
- provided
- true
-
+
+
+ cglib
+ cglib
+ 2.2.2
+ test
+
-
-
- org.springframework
- spring-test
- ${spring}
- test
-
-
- org.apache.openwebbeans.test
- cditest-owb
- ${webbeans}
- test
-
+
+
+ org.springframework.data
+ spring-data-commons
+ ${springdata.commons}
+
-
+
+
+ commons-lang
+ commons-lang
+ ${commonslang}
+
+
+ commons-collections
+ commons-collections
+ ${commonscollections}
+
-
-
-
+
+
+ joda-time
+ joda-time
+ ${jodatime}
+
+
+
+
+ org.elasticsearch
+ elasticsearch
+ ${elasticsearch}
+
+
+
+
+ org.codehaus.jackson
+ jackson-mapper-asl
+ ${jackson}
+
+
+
+
+ javax.enterprise
+ cdi-api
+ ${cdi}
+ provided
+ true
+
+
+
+
+ org.springframework
+ spring-test
+ ${spring}
+ test
+
+
+ org.apache.openwebbeans.test
+ cditest-owb
+ ${webbeans}
+ test
+
+
+
+
+
+
+ org.apache.maven.pluginsmaven-assembly-plugin
@@ -133,38 +134,39 @@
org.codehaus.mojowagon-maven-plugin
-
-
+
+
-
-
- biomedcentral
- BioMed Central Development Team
- +0
-
-
-
-
+
+
+ biomedcentral
+ BioMed Central Development Team
+ +0
+
+
+
+ spring-libs-snapshothttp://repo.springsource.org/lib-snapshot-local
-
+
- https://github.com/SpringSource/spring-data-elasticsearch
- scm:git:git://github.com/SpringSource/spring-data-elasticsearch.git
- scm:git:ssh://git@github.com:SpringSource/spring-data-elasticsearch.git
-
-
-
- Bamboo
- http://build.springsource.org/browse/SPRINGDATAESh
-
-
-
- JIRA
- https://jira.springsource.org/browse/DATAES
+ https://github.com/SpringSource/spring-data-elasticsearch
+ scm:git:git://github.com/SpringSource/spring-data-elasticsearch.git
+ scm:git:ssh://git@github.com:SpringSource/spring-data-elasticsearch.git
+
+
+
+
+ Bamboo
+ http://build.springsource.org/browse/SPRINGDATAES
+
+
+
+ JIRA
+ https://jira.springsource.org/browse/DATAES
diff --git a/src/docbkx/index.xml b/src/docbkx/index.xml
index 32621e38e..05f60dde7 100644
--- a/src/docbkx/index.xml
+++ b/src/docbkx/index.xml
@@ -5,11 +5,11 @@
Spring Data Elasticsearch
-
- BioMed Central
- Development Team
-
-
+
+ BioMed Central
+ Development Team
+
+
Copies of this document may be made for your own use and for
@@ -35,8 +35,10 @@
Reference Documentation
-
-
+
+
diff --git a/src/docbkx/preface.xml b/src/docbkx/preface.xml
index d376dadd3..2872ded1c 100644
--- a/src/docbkx/preface.xml
+++ b/src/docbkx/preface.xml
@@ -3,13 +3,16 @@
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
Preface
- The Spring Data Elasticsearch project applies core Spring concepts to
+ The Spring Data Elasticsearch project applies core Spring
+ concepts to
the
- development of solutions using the Elasticsearch Search Engine.
+ development of solutions using the Elasticsearch Search
+ Engine.
We have povided a "template" as a high-level abstraction for
- storing,querying,sorting and faceting documents. You will notice similarities
- to the Spring data solr and
- mongodb support in the Spring Framework.
+ storing,querying,sorting and faceting documents. You will notice
+ similarities
+ to the Spring data solr and
+ mongodb support in the Spring Framework.
Project Metadata
@@ -17,7 +20,8 @@
Version Control -
- git://github.com/BioMedCentralLtd/spring-data-elasticsearch.git
+ git://github.com/BioMedCentralLtd/spring-data-elasticsearch.git
@@ -28,7 +32,8 @@
Requires
Elasticsearch
- 0.20.2 and above or optional dependency or not even that if you are using Embedded Node Client
-
+ 0.20.2 and above or optional dependency or not even that if you are
+ using Embedded Node Client
+
\ No newline at end of file
diff --git a/src/docbkx/reference/data-elasticsearch.xml b/src/docbkx/reference/data-elasticsearch.xml
index 77e733330..ee3460570 100644
--- a/src/docbkx/reference/data-elasticsearch.xml
+++ b/src/docbkx/reference/data-elasticsearch.xml
@@ -15,8 +15,10 @@
Spring Namespace
- The Spring Data Elasticsearch module contains a custom namespace allowing
- definition of repository beans as well as elements for instantiating
+ The Spring Data Elasticsearch module contains a custom namespace
+ allowing
+ definition of repository beans as well as elements for
+ instantiating
a
ElasticsearchServer
.
@@ -32,7 +34,7 @@
Setting up Elasticsearch repositories using Namespace
-<?xml version="1.0" encoding="UTF-8"?>
+ <?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:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
@@ -56,7 +58,7 @@ http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.
Transport Client using Namespace
-<?xml version="1.0" encoding="UTF-8"?>
+ <?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:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
@@ -71,7 +73,7 @@ http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.
Node Client using Namespace
-<?xml version="1.0" encoding="UTF-8"?>
+ <?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:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
@@ -87,13 +89,15 @@ http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.
Annotation based configuration
- The Spring Data Elasticsearch repositories support cannot only be
+ The Spring Data Elasticsearch repositories support cannot only
+ be
activated through an XML namespace but also using an annotation
through JavaConfig.
- Spring Data Elasticsearch repositories using JavaConfig
-
+ Spring Data Elasticsearch repositories using JavaConfig
+
+
@Configuration
@EnableElasticsearchRepositories(basePackages = "org/springframework/data/elasticsearch/repositories")
static class Config {
@@ -122,12 +126,14 @@ return new ElasticsearchTemplate(nodeBuilder().local(true).node().client());
Elasticsearch Repositores using CDI
- The Spring Data Elasticsearch repositories can also be set up using CDI
+ The Spring Data Elasticsearch repositories can also be set up
+ using CDI
functionality.
- Spring Data Elasticsearch repositories using JavaConfig
-class ElasticsearchTemplateProducer {
+ Spring Data Elasticsearch repositories using JavaConfig
+
+ class ElasticsearchTemplateProducer {
@Produces
@ApplicationScoped
@@ -157,9 +163,11 @@ public void setRepository(ProductRepository repository) {
Query lookup strategies
- The Elasticsearch module supports all basic query building feature as String,Abstract,Criteria or
+ The Elasticsearch module supports all basic query building
+ feature as String,Abstract,Criteria or
have
- it being derived from the method name.
+ it being derived from the
+ method name.
@@ -180,11 +188,13 @@ public void setRepository(ProductRepository repository) {
Query creation
- Generally the query creation mechanism for Elasticsearch works as described
+ Generally the query creation mechanism for Elasticsearch works as
+ described
in
. Here's a short example
- of what a Elasticsearch query method translates into:
+ of what a Elasticsearch query method
+ translates into:
Query creation from method namespublic interface BookRepository extends Repository<Book, String> {
@@ -192,7 +202,7 @@ public void setRepository(ProductRepository repository) {
}
The method name above will be translated into the following
- Elasticsearch json query
+ Elasticsearch json query
{ "bool" :
@@ -227,7 +237,8 @@ public void setRepository(ProductRepository repository) {
findByNameAndPrice
- {"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
+ {"bool" : {"must" : [ {"field" : {"name" : "?"}},
+ {"field" : {"price" : "?"}} ]}}
@@ -238,7 +249,8 @@ public void setRepository(ProductRepository repository) {
findByNameOrPrice
- {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
+ {"bool" : {"should" : [ {"field" : {"name" : "?"}},
+ {"field" : {"price" : "?"}} ]}}
@@ -260,7 +272,8 @@ public void setRepository(ProductRepository repository) {
findByNameNot
- {"bool" : {"must_not" : {"field" : {"name" : "?"}}}}
+ {"bool" : {"must_not" : {"field" : {"name" : "?"}}}}
+
@@ -271,7 +284,9 @@ public void setRepository(ProductRepository repository) {
findByPriceBetween
- {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
+ {"bool" : {"must" : {"range" : {"price" : {"from" :
+ ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
+
@@ -282,7 +297,9 @@ public void setRepository(ProductRepository repository) {
findByPriceLessThan
- {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
+ {"bool" : {"must" : {"range" : {"price" : {"from" :
+ null,"to" : ?,"include_lower" : true,"include_upper" :
+ true}}}}}
@@ -293,7 +310,9 @@ public void setRepository(ProductRepository repository) {
findByPriceGreaterThan
- {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
+ {"bool" : {"must" : {"range" : {"price" : {"from" :
+ ?,"to" : null,"include_lower" : true,"include_upper" :
+ true}}}}}
@@ -304,7 +323,9 @@ public void setRepository(ProductRepository repository) {
findByPriceBefore
- {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
+ {"bool" : {"must" : {"range" : {"price" : {"from" :
+ null,"to" : ?,"include_lower" : true,"include_upper" :
+ true}}}}}
@@ -315,7 +336,9 @@ public void setRepository(ProductRepository repository) {
findByPriceAfter
- {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
+ {"bool" : {"must" : {"range" : {"price" : {"from" :
+ ?,"to" : null,"include_lower" : true,"include_upper" :
+ true}}}}}
@@ -326,7 +349,8 @@ public void setRepository(ProductRepository repository) {
findByNameLike
- {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
+ {"bool" : {"must" : {"field" : {"name" : {"query" :
+ "?*","analyze_wildcard" : true}}}}}
@@ -337,7 +361,8 @@ public void setRepository(ProductRepository repository) {
findByNameStartingWith
- {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
+ {"bool" : {"must" : {"field" : {"name" : {"query" :
+ "?*","analyze_wildcard" : true}}}}}
@@ -348,7 +373,8 @@ public void setRepository(ProductRepository repository) {
findByNameEndingWith
- {"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}
+ {"bool" : {"must" : {"field" : {"name" : {"query" :
+ "*?","analyze_wildcard" : true}}}}}
@@ -359,7 +385,8 @@ public void setRepository(ProductRepository repository) {
findByNameContaining
- {"bool" : {"must" : {"field" : {"name" : {"query" : "*?*","analyze_wildcard" : true}}}}}
+ {"bool" : {"must" : {"field" : {"name" : {"query" :
+ "*?*","analyze_wildcard" : true}}}}}
@@ -370,7 +397,8 @@ public void setRepository(ProductRepository repository) {
findByNameIn(Collection<String>names)
- {"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}
+ {"bool" : {"must" : {"bool" : {"should" : [ {"field" :
+ {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}
@@ -381,7 +409,8 @@ public void setRepository(ProductRepository repository) {
findByNameNotIn(Collection<String>names)
- {"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}
+ {"bool" : {"must_not" : {"bool" : {"should" : {"field" :
+ {"name" : "?"}}}}}}
@@ -403,7 +432,8 @@ public void setRepository(ProductRepository repository) {
findByAvailableTrue
- {"bool" : {"must" : {"field" : {"available" : true}}}}
+ {"bool" : {"must" : {"field" : {"available" : true}}}}
+
@@ -414,7 +444,8 @@ public void setRepository(ProductRepository repository) {
findByAvailableFalse
- {"bool" : {"must" : {"field" : {"available" : false}}}}
+ {"bool" : {"must" : {"field" : {"available" : false}}}}
+
@@ -425,7 +456,8 @@ public void setRepository(ProductRepository repository) {
findByAvailableTrueOrderByNameDesc
- {"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}
+ {"sort" : [{ "name" : {"order" : "desc"} }],"bool" :
+ {"must" : {"field" : {"available" : true}}}}
diff --git a/src/docbkx/reference/elasticsearch-misc.xml b/src/docbkx/reference/elasticsearch-misc.xml
index a5c3f935a..78aece686 100644
--- a/src/docbkx/reference/elasticsearch-misc.xml
+++ b/src/docbkx/reference/elasticsearch-misc.xml
@@ -6,9 +6,10 @@
This chapter covers additional support for Elasticsearch operations
- that cannot be directly accessed via the repository
+ that cannot be directly accessed via the repository
interface.
- It is recommended to add those operations as custom
+ It is
+ recommended to add those operations as custom
implementation as
described in
@@ -21,7 +22,7 @@
Filter Builder improves query speed.
-
+
private ElasticsearchTemplate elasticsearchTemplate;
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
@@ -31,18 +32,19 @@ Page<SampleEntity> sampleEntities = elasticsearchTemplate.queryForPage(sea
-
- Using Scan And Scroll For Big Result Set
-
- Elasticsearch has scan and scroll feature for getting big result set in chunks.
- ElasticsearchTemplate
- has scan and scroll methods that can be used as below.
-
-
-
- Using Scan and Scroll
-
-
+
+ Using Scan And Scroll For Big Result Set
+
+ Elasticsearch has scan and scroll feature for getting big result set
+ in chunks.
+ ElasticsearchTemplate
+ has scan and scroll methods that can be used as below.
+
+
+
+ Using Scan and Scroll
+
+
SearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(matchAllQuery())
.withIndices("test-index")
@@ -78,6 +80,6 @@ for(SearchHit searchHit : response.getHits()){
}
}
}
-
-
+
+
\ No newline at end of file
diff --git a/src/docbkx/reference/repositories.xml b/src/docbkx/reference/repositories.xml
index e9bd00853..b473c297e 100644
--- a/src/docbkx/reference/repositories.xml
+++ b/src/docbkx/reference/repositories.xml
@@ -2,70 +2,89 @@
- Repositories
+ Repositories
-
- Introduction
+
+ Introduction
- Implementing a data access layer of an application has been
- cumbersome for quite a while. Too much boilerplate code had to be written.
- Domain classes were anemic and not designed in a real object oriented or
- domain driven manner.
+ Implementing a data access layer of an application has been
+ cumbersome for quite a while. Too much boilerplate code had to be
+ written.
+ Domain classes were anemic and not designed in a real object oriented or
+ domain driven manner.
+
- Using both of these technologies makes developers life a lot easier
- regarding rich domain model's persistence. Nevertheless the amount of
- boilerplate code to implement repositories especially is still quite high.
- So the goal of the repository abstraction of Spring Data is to reduce the
- effort to implement data access layers for various persistence stores
- significantly.
+ Using both of these technologies makes developers life a lot
+ easier
+ regarding rich domain model's persistence. Nevertheless the amount of
+ boilerplate code to implement repositories especially is still quite
+ high.
+ So the goal of the repository abstraction of Spring Data is to reduce
+ the
+ effort to implement data access layers for various persistence stores
+ significantly.
+
- The following chapters will introduce the core concepts and
- interfaces of Spring Data repositories in general for detailled
- information on the specific features of a particular store consult the
- later chapters of this document.
+ The following chapters will introduce the core concepts and
+ interfaces of Spring Data repositories in general for detailled
+ information on the specific features of a particular store consult
+ the
+ later chapters of this document.
+
-
- As this part of the documentation is pulled in from Spring Data
- Commons we have to decide for a particular module to be used as example.
- The configuration and code samples in this chapter are using the JPA
- module. Make sure you adapt e.g. the XML namespace declaration, types to
- be extended to the equivalents of the module you're actually
- using.
-
-
+
+ As this part of the documentation is pulled in from Spring Data
+ Commons we have to decide for a particular module to be used as
+ example.
+ The configuration and code samples in this chapter are using the JPA
+ module. Make sure you adapt e.g. the XML namespace declaration,
+ types to
+ be extended to the equivalents of the module you're actually
+ using.
+
+
+
-
- Core concepts
+
+ Core concepts
- The central interface in Spring Data repository abstraction is
- Repository (probably not that much of a
- surprise). It is typeable to the domain class to manage as well as the id
- type of the domain class. This interface mainly acts as marker interface
- to capture the types to deal with and help us when discovering interfaces
- that extend this one. Beyond that there's
- CrudRepository which provides some
- sophisticated functionality around CRUD for the entity being
- managed.
+
+ The central interface in Spring Data repository abstraction is
+ Repository
+ (probably not that much of a
+ surprise). It is typeable to the domain class to manage as well as the id
+ type of the domain class. This interface mainly acts as marker interface
+ to capture the types to deal with and help us when discovering
+ interfaces
+ that extend this one. Beyond that there's
+ CrudRepository
+ which provides some
+ sophisticated functionality around CRUD for the entity being
+ managed.
+
-
- CrudRepository interface
+
+
+ CrudRepository
+ interface
+
-
-
-
+
+
+
-
+
-
+
-
+
-
+
-
-
+
+
- public interface CrudRepository<T, ID extends Serializable>
+ public interface CrudRepository<T, ID extends Serializable>
extends Repository<T, ID> {
T save(T entity);
@@ -83,88 +102,107 @@
// … more functionality omitted.
}
-
-
- Saves the given entity.
-
+
+
+ Saves the given entity.
+
-
- Returns the entity identified by the given id.
-
+
+ Returns the entity identified by the given id.
+
-
- Returns all entities.
-
+
+ Returns all entities.
+
-
- Returns the number of entities.
-
+
+ Returns the number of entities.
+
-
- Deletes the given entity.
-
+
+ Deletes the given entity.
+
-
- Returns whether an entity with the given id exists.
-
-
-
-
+
+ Returns whether an entity with the given id exists.
+
+
+
+
- Usually we will have persistence technology specific sub-interfaces
- to include additional technology specific methods. We will now ship
- implementations for a variety of Spring Data modules that implement this
- interface.
+ Usually we will have persistence technology specific
+ sub-interfaces
+ to include additional technology specific methods. We will now ship
+ implementations for a variety of Spring Data modules that implement
+ this
+ interface.
+
- On top of the CrudRepository there is
- a PagingAndSortingRepository abstraction
- that adds additional methods to ease paginated access to entities:
+
+ On top of the
+ CrudRepository
+ there is
+ a
+ PagingAndSortingRepository
+ abstraction
+ that adds additional methods to ease paginated access to entities:
+
-
- PagingAndSortingRepository
+
+ PagingAndSortingRepository
- public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {
+ public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
-
+
- Accessing the second page of User by a page
- size of 20 you could simply do something like this:
+
+ Accessing the second page of
+ User
+ by a page
+ size of 20 you could simply do something like this:
+
- PagingAndSortingRepository<User, Long> repository = // … get access to a bean
+ PagingAndSortingRepository<User, Long> repository = // … get access to a bean
Page<User> users = repository.findAll(new PageRequest(1, 20));
-
+
-
- Query methods
+
+ Query methods
- Next to standard CRUD functionality repositories are usually queries
- on the underlying datastore. With Spring Data declaring those queries
- becomes a four-step process:
+ Next to standard CRUD functionality repositories are usually
+ queries
+ on the underlying datastore. With Spring Data declaring those queries
+ becomes a four-step process:
+
-
-
- Declare an interface extending
- Repository or one of its sub-interfaces
- and type it to the domain class it shall handle.
+
+
+
+ Declare an interface extending
+ Repository
+ or one of its sub-interfaces
+ and type it to the domain class it shall handle.
+
- public interface PersonRepository extends Repository<User, Long> { … }
-
+ public interface PersonRepository extends Repository<User, Long> { … }
+
-
- Declare query methods on the interface.
+
+ Declare query methods on the interface.
- List<Person> findByLastname(String lastname);
-
+ List<Person> findByLastname(String lastname);
+
-
- Setup Spring to create proxy instances for those
- interfaces.
+
+ Setup Spring to create proxy instances for those
+ interfaces.
+
- <?xml version="1.0" encoding="UTF-8"?>
+ <?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/data/jpa"
@@ -177,19 +215,25 @@
</beans>
-
- Note that we use the JPA namespace here just by example. If
- you're using the repository abstraction for any other store you need
- to change this to the appropriate namespace declaration of your
- store module which should be exchanging jpa in favor of
- e.g. mongodb.
-
-
+
+
+ Note that we use the JPA namespace here just by example. If
+ you're using the repository abstraction for any other store you need
+ to change this to the appropriate namespace declaration of your
+ store module which should be exchanging
+ jpa
+ in favor of
+ e.g.
+ mongodb
+ .
+
+
+
-
- Get the repository instance injected and use it.
+
+ Get the repository instance injected and use it.
- public class SomeClient {
+ public class SomeClient {
@Autowired
private PersonRepository repository;
@@ -197,44 +241,61 @@
public void doSomething() {
List<Person> persons = repository.findByLastname("Matthews");
}
-
-
+
+
- At this stage we barely scratched the surface of what's possible
- with the repositories but the general approach should be clear. Let's go
- through each of these steps and figure out details and various options
- that you have at each stage.
+ At this stage we barely scratched the surface of what's possible
+ with the repositories but the general approach should be clear. Let's
+ go
+ through each of these steps and figure out details and various options
+ that you have at each stage.
+
-
- Defining repository interfaces
+
+ Defining repository interfaces
- As a very first step you define a domain class specific repository
- interface. It's got to 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.
+
+ As a very first step you define a domain class specific repository
+ interface. It's got to 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
+ .
+
-
- Fine tuning repository definition
+
+ Fine tuning repository definition
- Usually you will have your repository interface extend
- Repository,
- CrudRepository or
- PagingAndSortingRepository. If you
- don't like extending Spring Data interfaces at all you can also
- annotate your repository interface with
- @RepositoryDefinition. Extending
- CrudRepository will expose a complete
- set of methods to manipulate your entities. If you would rather be
- selective about the methods being exposed, simply copy the ones you
- want to expose from CrudRepository into
- your domain repository.
+
+ Usually you will have your repository interface extend
+ Repository
+ ,
+ CrudRepository
+ or
+ PagingAndSortingRepository
+ . If you
+ don't like extending Spring Data interfaces at all you can also
+ annotate your repository interface with
+ @RepositoryDefinition
+ . Extending
+ CrudRepository
+ will expose a complete
+ set of methods to manipulate your entities. If you would rather be
+ selective about the methods being exposed, simply copy the ones you
+ want to expose from
+ CrudRepository
+ into
+ your domain repository.
+
-
- Selectively exposing CRUD methods
+
+ Selectively exposing CRUD methods
- interface MyBaseRepository<T, ID extends Serializable> extends Repository<T, ID> {
+ interface MyBaseRepository<T, ID extends Serializable> extends Repository<T, ID> {
T findOne(ID id);
T save(T entity);
}
@@ -243,205 +304,307 @@
User findByEmailAddress(EmailAddress emailAddress);
}
-
+
- In the first step we define a common base interface for all our
- domain repositories and expose findOne(…) as
- well as save(…).These methods will be routed
- into the base repository implementation of the store of your choice
- because they are matching the method signatures in
- CrudRepository. So our
- UserRepository will now be able to save
- users, find single ones by id as well as triggering a query to find
- Users by their email address.
-
-
+
+ In the first step we define a common base interface for all our
+ domain repositories and expose
+ findOne(…)
+ as
+ well as
+ save(…)
+ .These methods will be routed
+ into the base repository implementation of the store of your choice
+ because they are matching the method signatures in
+ CrudRepository
+ . So our
+ UserRepository
+ will now be able to save
+ users, find single ones by id as well as triggering a query to find
+ User
+ s by their email address.
+
+
+
-
- Defining query methods
+
+ Defining query methods
-
- Query lookup strategies
+
+ Query lookup strategies
- The next thing we have to discuss is the definition of query
- methods. There are two main ways that the repository proxy is able to
- come up with the store specific query from the method name. The first
- option is to derive the query from the method name directly, the
- second is using some kind of additionally created query. What detailed
- options are available pretty much depends on the actual store,
- however, there's got to be some algorithm that decides what actual
- query is created.
+ The next thing we have to discuss is the definition of query
+ methods. There are two main ways that the repository proxy is able
+ to
+ come up with the store specific query from the method name. The first
+ option is to derive the query from the method name directly, the
+ second is using some kind of additionally created query. What
+ detailed
+ options are available pretty much depends on the actual store,
+ however, there's got to be some algorithm that decides what actual
+ query is created.
+
- There are three strategies available for the repository
- infrastructure to resolve the query. The strategy to be used can be
- configured at the namespace through the
- query-lookup-strategy attribute. However, It might be the
- case that some of the strategies are not supported for specific
- datastores. Here are your options:
+
+ There are three strategies available for the repository
+ infrastructure to resolve the query. The strategy to be used can be
+ configured at the namespace through the
+ query-lookup-strategy
+ attribute. However, It might be the
+ case that some of the strategies are not supported for specific
+ datastores. Here are your options:
+
-
- CREATE
+
+ CREATE
- This strategy will try to construct a store specific query
- from the query method's name. The general approach is to remove a
- given set of well-known prefixes from the method name and parse the
- rest of the method. Read more about query construction in .
-
+
+ This strategy will try to construct a store specific query
+ from the query method's name. The general approach is to remove a
+ given set of well-known prefixes from the method name and parse
+ the
+ rest of the method. Read more about query construction in
+
+ .
+
+
-
- USE_DECLARED_QUERY
+
+ USE_DECLARED_QUERY
- This strategy tries to find a declared query which will be
- used for execution first. The query could be defined by an
- annotation somewhere or declared by other means. Please consult the
- documentation of the specific store to find out what options are
- available for that store. If the repository infrastructure does not
- find a declared query for the method at bootstrap time it will
- fail.
-
+ This strategy tries to find a declared query which will be
+ used for execution first. The query could be defined by an
+ annotation somewhere or declared by other means. Please consult
+ the
+ documentation of the specific store to find out what options are
+ available for that store. If the repository infrastructure does not
+ find a declared query for the method at bootstrap time it will
+ fail.
+
+
-
- CREATE_IF_NOT_FOUND (default)
+
+ CREATE_IF_NOT_FOUND (default)
- This strategy is actually a combination of CREATE
- and USE_DECLARED_QUERY. It will try to lookup a
- declared query first but create a custom method name based query if
- no declared query was found. This is the default lookup strategy and
- thus will be used if you don't configure anything explicitly. It
- allows quick query definition by method names but also custom tuning
- of these queries by introducing declared queries as needed.
-
-
+
+ This strategy is actually a combination of
+ CREATE
+ and
+ USE_DECLARED_QUERY
+ . It will try to lookup a
+ declared query first but create a custom method name based query if
+ no declared query was found. This is the default lookup strategy and
+ thus will be used if you don't configure anything explicitly. It
+ allows quick query definition by method names but also custom
+ tuning
+ of these queries by introducing declared queries as needed.
+
+
+
-
- Query creation
+
+ Query creation
- The query builder mechanism built into Spring Data repository
- infrastructure is useful to build constraining queries over entities
- of the repository. We will strip the prefixes findBy,
- find, readBy, read,
- getBy as well as get from the method and
- start parsing the rest of it. At a very basic level you can define
- conditions on entity properties and concatenate them with
- AND and OR.
+
+ The query builder mechanism built into Spring Data repository
+ infrastructure is useful to build constraining queries over
+ entities
+ of the repository. We will strip the prefixes
+ findBy
+ ,
+ find
+ ,
+ readBy
+ ,
+ read
+ ,
+ getBy
+ as well as
+ get
+ from the method and
+ start parsing the rest of it. At a very basic level you can define
+ conditions on entity properties and concatenate them with
+ AND
+ and
+ OR
+ .
+
-
- Query creation from method names
+
+ Query creation from method names
- public interface PersonRepository extends Repository<User, Long> {
+
+ public interface PersonRepository extends Repository<User, Long> {
List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);
- }
-
+ }
+
+
- The actual result of parsing that method will of course depend
- on the persistence store we create the query for, however, there are
- some general things to notice. The expressions are usually property
- traversals combined with operators that can be concatenated. As you
- can see in the example you can combine property expressions with And
- and Or. Beyond that you also get support for various operators like
- Between, LessThan,
- GreaterThan, Like for the
- property expressions. As the operators supported can vary from
- datastore to datastore please consult the according part of the
- reference documentation.
+
+ The actual result of parsing that method will of course depend
+ on the persistence store we create the query for, however, there are
+ some general things to notice. The expressions are usually property
+ traversals combined with operators that can be concatenated. As you
+ can see in the example you can combine property expressions with
+ And
+ and Or. Beyond that you also get support for various operators like
+ Between
+ ,
+ LessThan
+ ,
+ GreaterThan
+ ,
+ Like
+ for the
+ property expressions. As the operators supported can vary from
+ datastore to datastore please consult the according part of the
+ reference documentation.
+
-
- Property expressions
+
+ Property expressions
- Property expressions can just refer to a direct property of
- the managed entity (as you just saw in the example above). On query
- creation time we already make sure that the parsed property is at a
- property of the managed domain class. However, you can also define
- constraints by traversing nested properties. Assume
- Persons have Addresses
- with ZipCodes. In that case a method name
- of
+
+ Property expressions can just refer to a direct property of
+ the managed entity (as you just saw in the example above). On query
+ creation time we already make sure that the parsed property is at
+ a
+ property of the managed domain class. However, you can also define
+ constraints by traversing nested properties. Assume
+ Person
+ s have
+ Address
+ es
+ with
+ ZipCode
+ s. In that case a method name
+ of
+
- List<Person> findByAddressZipCode(ZipCode zipCode);
+ List<Person> findByAddressZipCode(ZipCode zipCode);
- will create the property traversal
- x.address.zipCode. The resolution algorithm starts with
- interpreting the entire part (AddressZipCode) as
- property and checks the domain class for a property with that name
- (uncapitalized). If it succeeds it just uses that. If not it starts
- splitting up the source at the camel case parts from the right side
- into a head and a tail and tries to find the according property,
- e.g. AddressZip and Code. If
- we find a property with that head we take the tail and continue
- building the tree down from there. As in our case the first split
- does not match we move the split point to the left
- (Address, ZipCode).
+
+ will create the property traversal
+ x.address.zipCode
+ . The resolution algorithm starts with
+ interpreting the entire part (
+ AddressZipCode
+ ) as
+ property and checks the domain class for a property with that name
+ (uncapitalized). If it succeeds it just uses that. If not it
+ starts
+ splitting up the source at the camel case parts from the right side
+ into a head and a tail and tries to find the according property,
+ e.g.
+ AddressZip
+ and
+ Code
+ . If
+ we find a property with that head we take the tail and continue
+ building the tree down from there. As in our case the first split
+ does not match we move the split point to the left
+ (
+ Address
+ ,
+ ZipCode
+ ).
+
- Although this should work for most cases, there might be cases
- where the algorithm could select the wrong property. Suppose our
- Person class has an addressZip
- property as well. Then our algorithm would match in the first split
- round already and essentially choose the wrong property and finally
- fail (as the type of addressZip probably has
- no code property). To resolve this ambiguity you can use
- _ inside your method name to manually define
- traversal points. So our method name would end up like so:
+
+ Although this should work for most cases, there might be cases
+ where the algorithm could select the wrong property. Suppose our
+ Person
+ class has an
+ addressZip
+ property as well. Then our algorithm would match in the first
+ split
+ round already and essentially choose the wrong property and finally
+ fail (as the type of
+ addressZip
+ probably has
+ no code property). To resolve this ambiguity you can use
+ _
+ inside your method name to manually define
+ traversal points. So our method name would end up like so:
+
- List<Person> findByAddress_ZipCode(ZipCode zipCode);
+ List<Person> findByAddress_ZipCode(ZipCode zipCode);
-
-
+
+
-
- Special parameter handling
+
+ Special parameter handling
- To hand parameters to your query you simply define method
- parameters as already seen in the examples above. Besides that we will
- recognizes certain specific types to apply pagination and sorting to
- your queries dynamically.
+ To hand parameters to your query you simply define method
+ parameters as already seen in the examples above. Besides that we
+ will
+ recognizes certain specific types to apply pagination and sorting to
+ your queries dynamically.
+
-
- Using Pageable and Sort in query methods
+
+ Using Pageable and Sort in query methods
- Page<User> findByLastname(String lastname, Pageable pageable);
+ Page<User> findByLastname(String lastname, Pageable pageable);
List<User> findByLastname(String lastname, Sort sort);
List<User> findByLastname(String lastname, Pageable pageable);
-
+
- The first method allows you to pass a Pageable
- instance to the query method to dynamically add paging to your
- statically defined query. Sorting options are handed via
- the Pageable instance too. If you only
- need sorting, simply add a Sort parameter to your method.
- As you also can see, simply returning a
- List is possible as well. We will then
- not retrieve the additional metadata required to build the actual
- Page instance but rather simply
- restrict the query to lookup only the given range of entities.
+
+ The first method allows you to pass a
+ Pageable
+ instance to the query method to dynamically add paging to your
+ statically defined query.
+ Sorting
+ options are handed via
+ the
+ Pageable
+ instance too. If you only
+ need sorting, simply add a
+ Sort
+ parameter to your method.
+ As you also can see, simply returning a
+ List
+ is possible as well. We will then
+ not retrieve the additional metadata required to build the actual
+ Page
+ instance but rather simply
+ restrict the query to lookup only the given range of entities.
+
-
- To find out how many pages you get for a query entirely we
- have to trigger an additional count query. This will be derived from
- the query you actually trigger by default.
-
-
-
+
+ To find out how many pages you get for a query entirely we
+ have to trigger an additional count query. This will be derived
+ from
+ the query you actually trigger by default.
+
+
+
+
-
- Creating repository instances
+
+ Creating repository instances
- So now the question is how to create instances and bean
- definitions for the repository interfaces defined.
+ So now the question is how to create instances and bean
+ definitions for the repository interfaces defined.
+
-
- XML Configuration
+
+ XML Configuration
- The easiest way to do so is by using the Spring namespace that
- is shipped with each Spring Data module that supports the repository
- mechanism. Each of those includes a repositories element that allows
- you to simply define a base package that Spring will scan for
- you.
+ The easiest way to do so is by using the Spring namespace that
+ is shipped with each Spring Data module that supports the
+ repository
+ mechanism. Each of those includes a repositories element that allows
+ you to simply define a base package that Spring will scan for
+ you.
+
- <?xml version="1.0" encoding="UTF-8"?>
+ <?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/data/jpa"
@@ -454,75 +617,109 @@
</beans:beans>
- In this case we instruct Spring to scan
- com.acme.repositories and all its sub packages for
- interfaces extending Repository or one
- of its sub-interfaces. For each interface found it will register the
- persistence technology specific
- FactoryBean to create the according
- proxies that handle invocations of the query methods. Each of these
- beans will be registered under a bean name that is derived from the
- interface name, so an interface of
- UserRepository would be registered
- under userRepository. The base-package
- attribute allows the use of wildcards, so that you can have a pattern
- of scanned packages.
+
+ In this case we instruct Spring to scan
+ com.acme.repositories
+ and all its sub packages for
+ interfaces extending
+ Repository
+ or one
+ of its sub-interfaces. For each interface found it will register the
+ persistence technology specific
+ FactoryBean
+ to create the according
+ proxies that handle invocations of the query methods. Each of these
+ beans will be registered under a bean name that is derived from the
+ interface name, so an interface of
+ UserRepository
+ would be registered
+ under
+ userRepository
+ . The
+ base-package
+ attribute allows the use of wildcards, so that you can have a
+ pattern
+ of scanned packages.
+
-
- Using filters
+
+ Using filters
- By default we will pick up every interface extending the
- persistence technology specific
- Repository sub-interface located
- underneath the configured base package and create a bean instance
- for it. However, you might want finer grained control over which
- interfaces bean instances get created for. To do this we support the
- use of <include-filter /> and
- <exclude-filter /> elements inside
- <repositories />. The semantics are exactly
- equivalent to the elements in Spring's context namespace. For
- details see Spring reference documentation on these
- elements.
+
+ By default we will pick up every interface extending the
+ persistence technology specific
+ Repository
+ sub-interface located
+ underneath the configured base package and create a bean instance
+ for it. However, you might want finer grained control over which
+ interfaces bean instances get created for. To do this we support
+ the
+ use of
+ <include-filter />
+ and
+ <exclude-filter />
+ elements inside
+ <repositories />
+ . The semantics are exactly
+ equivalent to the elements in Spring's context namespace. For
+ details see
+ Spring reference documentation
+ on these
+ elements.
+
- E.g. to exclude certain interfaces from instantiation as
- repository, you could use the following configuration:
+ E.g. to exclude certain interfaces from instantiation as
+ repository, you could use the following configuration:
+
-
- Using exclude-filter element
+
+ Using exclude-filter element
- <repositories base-package="com.acme.repositories">
+ <repositories base-package="com.acme.repositories">
<context:exclude-filter type="regex" expression=".*SomeRepository" />
</repositories>
- This would exclude all interfaces ending in
- SomeRepository from being
- instantiated.
-
-
-
+
+ This would exclude all interfaces ending in
+ SomeRepository
+ from being
+ instantiated.
+
+
+
+
-
- JavaConfig
+
+ JavaConfig
- The repository infrastructure can also be triggered using a
- store-specific
- @Enable${store}Repositories annotation
- on a JavaConfig class. For an introduction into Java based
- configuration of the Spring container please have a look at the
- reference documentation.
- JavaConfig in the Spring reference documentation -
-
+
+ The repository infrastructure can also be triggered using a
+ store-specific
+ @Enable${store}Repositories
+ annotation
+ on a JavaConfig class. For an introduction into Java based
+ configuration of the Spring container please have a look at the
+ reference documentation.
+
+
+ JavaConfig in the Spring reference documentation -
+
+
+
+
- A sample configuration to enable Spring Data repositories would
- look something like this.
+ A sample configuration to enable Spring Data repositories
+ would
+ look something like this.
+
-
- Sample annotation based repository configuration
+
+ Sample annotation based repository configuration
- @Configuration
+ @Configuration
@EnableJpaRepositories("com.acme.repositories")
class ApplicationConfiguration {
@@ -531,179 +728,231 @@
// …
}
}
-
+
- Note that the sample uses the JPA specific annotation which
- would have to be exchanged dependingon which store module you actually
- use. The same applies to the definition of the
- EntityManagerFactory bean. Please
- consult the sections covering the store-specific configuration.
-
+
+ Note that the sample uses the JPA specific annotation which
+ would have to be exchanged dependingon which store module you actually
+ use. The same applies to the definition of the
+ EntityManagerFactory
+ bean. Please
+ consult the sections covering the store-specific configuration.
+
+
-
- Standalone usage
+
+ Standalone usage
- You can also use the repository infrastructure outside of a
- Spring container usage. You will still need to have some of the Spring
- libraries on your classpath but you can generally setup repositories
- programmatically as well. The Spring Data modules providing repository
- support ship a persistence technology specific
- RepositoryFactory that can be used as
- follows:
+
+ You can also use the repository infrastructure outside of a
+ Spring container usage. You will still need to have some of the Spring
+ libraries on your classpath but you can generally setup
+ repositories
+ programmatically as well. The Spring Data modules providing repository
+ support ship a persistence technology specific
+ RepositoryFactory
+ that can be used as
+ follows:
+
-
- Standalone usage of repository factory
+
+ Standalone usage of repository factory
- RepositoryFactorySupport factory = … // Instantiate factory here
+ RepositoryFactorySupport factory = … // Instantiate factory here
UserRepository repository = factory.getRepository(UserRepository.class);
-
-
-
-
+
+
+
+
-
- Custom implementations
+
+ Custom implementations
-
- Adding behaviour to single repositories
+
+ Adding behaviour to single repositories
- Often it is necessary to provide a custom implementation for a few
- repository methods. Spring Data repositories easily allow you to provide
- custom repository code and integrate it with generic CRUD abstraction
- and query method functionality. To enrich a repository with custom
- functionality you have to define an interface and an implementation for
- that functionality first and let the repository interface you provided
- so far extend that custom interface.
+ Often it is necessary to provide a custom implementation for a
+ few
+ repository methods. Spring Data repositories easily allow you to provide
+ custom repository code and integrate it with generic CRUD
+ abstraction
+ and query method functionality. To enrich a repository with custom
+ functionality you have to define an interface and an implementation
+ for
+ that functionality first and let the repository interface you provided
+ so far extend that custom interface.
+
-
- Interface for custom repository functionality
+
+ Interface for custom repository functionality
- interface UserRepositoryCustom {
+ interface UserRepositoryCustom {
public void someCustomMethod(User user);
}
-
+
-
- Implementation of custom repository functionality
+
+ Implementation of custom repository functionality
- class UserRepositoryImpl implements UserRepositoryCustom {
+
+ class UserRepositoryImpl implements UserRepositoryCustom {
public void someCustomMethod(User user) {
// Your custom implementation
}
- }Note that the implementation itself does not depend on
- Spring Data and can be a regular Spring bean. So you can use standard
- dependency injection behaviour to inject references to other beans,
- take part in aspects and so on.
-
+ }
+ Note that the implementation itself does not depend on
+ Spring Data and can be a regular Spring bean. So you can use standard
+ dependency injection behaviour to inject references to other beans,
+ take part in aspects and so on.
+
+
-
- Changes to the your basic repository interface
+
+ Changes to the your basic repository interface
- public interface UserRepository extends CrudRepository<User, Long>, UserRepositoryCustom {
+
+ public interface UserRepository extends CrudRepository<User, Long>, UserRepositoryCustom {
// Declare query methods here
- }Let your standard repository interface extend the custom
- one. This makes CRUD and custom functionality available to
- clients.
-
+ }
+ Let your standard repository interface extend the custom
+ one. This makes CRUD and custom functionality available to
+ clients.
+
+
-
- Configuration
+
+ Configuration
- If you use namespace configuration the repository infrastructure
- tries to autodetect custom implementations by looking up classes in
- the package we found a repository using the naming conventions
- appending the namespace element's attribute
- repository-impl-postfix to the classname. This suffix
- defaults to Impl.
+
+ If you use namespace configuration the repository infrastructure
+ tries to autodetect custom implementations by looking up classes in
+ the package we found a repository using the naming conventions
+ appending the namespace element's attribute
+ repository-impl-postfix
+ to the classname. This suffix
+ defaults to
+ Impl
+ .
+
-
- Configuration example
+
+ Configuration example
- <repositories base-package="com.acme.repository" />
+
+ <repositories base-package="com.acme.repository" />
- <repositories base-package="com.acme.repository" repository-impl-postfix="FooBar" />
-
+ <repositories base-package="com.acme.repository" repository-impl-postfix="FooBar" />
+
+
- The first configuration example will try to lookup a class
- com.acme.repository.UserRepositoryImpl to act
- as custom repository implementation, where the second example will try
- to lookup
- com.acme.repository.UserRepositoryFooBar.
-
+
+ The first configuration example will try to lookup a class
+ com.acme.repository.UserRepositoryImpl
+ to act
+ as custom repository implementation, where the second example will
+ try
+ to lookup
+ com.acme.repository.UserRepositoryFooBar
+ .
+
+
-
- Manual wiring
+
+ Manual wiring
- The approach above works perfectly well if your custom
- implementation uses annotation based configuration and autowiring
- entirely as it will be treated as any other Spring bean. If your
- custom implementation bean needs some special wiring you simply
- declare the bean and name it after the conventions just described. We
- will then pick up the custom bean by name rather than creating an
- instance.
+ The approach above works perfectly well if your custom
+ implementation uses annotation based configuration and autowiring
+ entirely as it will be treated as any other Spring bean. If your
+ custom implementation bean needs some special wiring you simply
+ declare the bean and name it after the conventions just described.
+ We
+ will then pick up the custom bean by name rather than creating an
+ instance.
+
-
- Manual wiring of custom implementations (I)
+
+ Manual wiring of custom implementations (I)
- <repositories base-package="com.acme.repository" />
+ <repositories base-package="com.acme.repository" />
<beans:bean id="userRepositoryImpl" class="…">
<!-- further configuration -->
</beans:bean>
-
-
-
+
+
+
-
- Adding custom behaviour to all repositories
+
+ Adding custom behaviour to all repositories
- In other cases you might want to add a single method to all of
- your repository interfaces. So the approach just shown is not feasible.
- The first step to achieve this is adding and intermediate interface to
- declare the shared behaviour
+ In other cases you might want to add a single method to all of
+ your repository interfaces. So the approach just shown is not
+ feasible.
+ The first step to achieve this is adding and intermediate interface to
+ declare the shared behaviour
+
-
- An interface declaring custom shared behaviour
+
+ An interface declaring custom shared behaviour
-
+
+
public interface MyRepository<T, ID extends Serializable>
extends JpaRepository<T, ID> {
void sharedCustomMethod(ID id);
- }
-
+ }
+
+
- Now your individual repository interfaces will extend this
- intermediate interface instead of the
- Repository interface to include the
- functionality declared. The second step is to create an implementation
- of this interface that extends the persistence technology specific
- repository base class which will then act as a custom base class for the
- repository proxies.
+
+ Now your individual repository interfaces will extend this
+ intermediate interface instead of the
+ Repository
+ interface to include the
+ functionality declared. The second step is to create an implementation
+ of this interface that extends the persistence technology specific
+ repository base class which will then act as a custom base class for
+ the
+ repository proxies.
+
-
- The default behaviour of the Spring <repositories
- /> namespace is to provide an implementation for all
- interfaces that fall under the base-package. This means
- that if left in it's current state, an implementation instance of
- MyRepository will be created by Spring.
- This is of course not desired as it is just supposed to act as an
- intermediary between Repository and the
- actual repository interfaces you want to define for each entity. To
- exclude an interface extending
- Repository from being instantiated as a
- repository instance it can either be annotate it with
- @NoRepositoryBean or moved out side of
- the configured base-package.
-
+
+
+ The default behaviour of the Spring
+ <repositories
+ />
+ namespace is to provide an implementation for all
+ interfaces that fall under the
+ base-package
+ . This means
+ that if left in it's current state, an implementation instance of
+ MyRepository
+ will be created by Spring.
+ This is of course not desired as it is just supposed to act as an
+ intermediary between
+ Repository
+ and the
+ actual repository interfaces you want to define for each entity. To
+ exclude an interface extending
+ Repository
+ from being instantiated as a
+ repository instance it can either be annotate it with
+ @NoRepositoryBean
+ or moved out side of
+ the configured
+ base-package
+ .
+
+
-
- Custom repository base class
+
+ Custom repository base class
-
+
public class MyRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID> implements MyRepository<T, ID> {
@@ -721,21 +970,30 @@
// implementation goes here
}
}
-
+
- The last step is to create a custom repository factory to replace
- the default RepositoryFactoryBean that will in
- turn produce a custom RepositoryFactory. The new
- repository factory will then provide your
- MyRepositoryImpl as the implementation of any
- interfaces that extend the Repository
- interface, replacing the SimpleJpaRepository
- implementation you just extended.
+
+ The last step is to create a custom repository factory to replace
+ the default
+ RepositoryFactoryBean
+ that will in
+ turn produce a custom
+ RepositoryFactory
+ . The new
+ repository factory will then provide your
+ MyRepositoryImpl
+ as the implementation of any
+ interfaces that extend the
+ Repository
+ interface, replacing the
+ SimpleJpaRepository
+ implementation you just extended.
+
-
- Custom repository factory bean
+
+ Custom repository factory bean
-
+
public class MyRepositoryFactoryBean<R extends JpaRepository<T, I>, T, I extends Serializable>
extends JpaRepositoryFactoryBean<R, T, I> {
@@ -767,39 +1025,48 @@
}
}
}
-
+
- Finally you can either declare beans of the custom factory
- directly or use the factory-class attribute of the Spring
- namespace to tell the repository infrastructure to use your custom
- factory implementation.
+
+ Finally you can either declare beans of the custom factory
+ directly or use the
+ factory-class
+ attribute of the Spring
+ namespace to tell the repository infrastructure to use your custom
+ factory implementation.
+
-
- Using the custom factory with the namespace
+
+ Using the custom factory with the namespace
- <repositories base-package="com.acme.repository"
+ <repositories base-package="com.acme.repository"
factory-class="com.acme.MyRepositoryFactoryBean" />
-
-
-
+
+
+
-
- Extensions
+
+ Extensions
- This chapter documents a set of Spring Data extensions that enable
- Spring Data usage in a variety of contexts. Currently most of the
- integration is targeted towards Spring MVC.
+ This chapter documents a set of Spring Data extensions that
+ enable
+ Spring Data usage in a variety of contexts. Currently most of the
+ integration is targeted towards Spring MVC.
+
-
- Domain class web binding for Spring MVC
+
+ Domain class web binding for Spring MVC
- Given you are developing a Spring MVC web applications you
- typically have to resolve domain class ids from URLs. By default it's
- your task to transform that request parameter or URL part into the
- domain class to hand it layers below then or execute business logic on
- the entities directly. This should look something like this:
+ Given you are developing a Spring MVC web applications you
+ typically have to resolve domain class ids from URLs. By default
+ it's
+ your task to transform that request parameter or URL part into the
+ domain class to hand it layers below then or execute business logic
+ on
+ the entities directly. This should look something like this:
+
- @Controller
+ @Controller
@RequestMapping("/users")
public class UserController {
@@ -820,26 +1087,39 @@
}
}
- First you pretty much have to declare a repository dependency for
- each controller to lookup the entity managed by the controller or
- repository respectively. Beyond that looking up the entity is
- boilerplate as well as it's always a findOne(…)
- call. Fortunately Spring provides means to register custom converting
- components that allow conversion between a String
- value to an arbitrary type.
+
+ First you pretty much have to declare a repository dependency for
+ each controller to lookup the entity managed by the controller or
+ repository respectively. Beyond that looking up the entity is
+ boilerplate as well as it's always a
+ findOne(…)
+ call. Fortunately Spring provides means to register custom
+ converting
+ components that allow conversion between a
+ String
+ value to an arbitrary type.
+
-
- PropertyEditors
+
+ PropertyEditors
- For versions up to Spring 3.0 simple Java
- PropertyEditors had to be used. Thus,
- we offer a DomainClassPropertyEditorRegistrar,
- that will look up all Spring Data repositories registered in the
- ApplicationContext and register a
- custom PropertyEditor for the managed
- domain class
+
+ For versions up to Spring 3.0 simple Java
+ PropertyEditor
+ s had to be used. Thus,
+ we offer a
+ DomainClassPropertyEditorRegistrar
+ ,
+ that will look up all Spring Data repositories registered in the
+ ApplicationContext
+ and register a
+ custom
+ PropertyEditor
+ for the managed
+ domain class
+
- <bean class="….web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
+ <bean class="….web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="webBindingInitializer">
<bean class="….web.bind.support.ConfigurableWebBindingInitializer">
<property name="propertyEditorRegistrars">
@@ -849,11 +1129,12 @@
</property>
</bean>
- If you have configured Spring MVC like this you can turn your
- controller into the following that reduces a lot of the clutter and
- boilerplate.
+ If you have configured Spring MVC like this you can turn your
+ controller into the following that reduces a lot of the clutter and
+ boilerplate.
+
- @Controller
+ @Controller
@RequestMapping("/users")
public class UserController {
@@ -865,25 +1146,32 @@
return "userForm";
}
}
-
+
-
- ConversionService
+
+ ConversionService
- As of Spring 3.0 the
- PropertyEditor support is superseeded
- by a new conversion infrstructure that leaves all the drawbacks of
- PropertyEditors behind and uses a
- stateless X to Y conversion approach. We now ship with a
- DomainClassConverter that pretty much mimics
- the behaviour of
- DomainClassPropertyEditorRegistrar. To register
- the converter you have to declare
- ConversionServiceFactoryBean, register the
- converter and tell the Spring MVC namespace to use the configured
- conversion service:
+
+ As of Spring 3.0 the
+ PropertyEditor
+ support is superseeded
+ by a new conversion infrstructure that leaves all the drawbacks of
+ PropertyEditor
+ s behind and uses a
+ stateless X to Y conversion approach. We now ship with a
+ DomainClassConverter
+ that pretty much mimics
+ the behaviour of
+ DomainClassPropertyEditorRegistrar
+ . To register
+ the converter you have to declare
+ ConversionServiceFactoryBean
+ , register the
+ converter and tell the Spring MVC namespace to use the configured
+ conversion service:
+
- <mvc:annotation-driven conversion-service="conversionService" />
+ <mvc:annotation-driven conversion-service="conversionService" />
<bean id="conversionService" class="….context.support.ConversionServiceFactoryBean">
<property name="converters">
@@ -894,13 +1182,13 @@
</list>
</property>
</bean>
-
-
+
+
-
- Web pagination
+
+ Web pagination
- @Controller
+ @Controller
@RequestMapping("/users")
public class UserController {
@@ -916,16 +1204,22 @@
}
}
- As you can see the naive approach requires the method to contain
- an HttpServletRequest parameter that has
- to be parsed manually. We even omitted an appropriate failure handling
- which would make the code even more verbose. The bottom line is that the
- controller actually shouldn't have to handle the functionality of
- extracting pagination information from the request. So we include a
- PageableArgumentResolver that will do the work
- for you.
+
+ As you can see the naive approach requires the method to contain
+ an
+ HttpServletRequest
+ parameter that has
+ to be parsed manually. We even omitted an appropriate failure handling
+ which would make the code even more verbose. The bottom line is that
+ the
+ controller actually shouldn't have to handle the functionality of
+ extracting pagination information from the request. So we include a
+ PageableArgumentResolver
+ that will do the work
+ for you.
+
- <bean class="….web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
+ <bean class="….web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="customArgumentResolvers">
<list>
<bean class="org.springframework.data.web.PageableArgumentResolver" />
@@ -933,10 +1227,11 @@
</property>
</bean>
- This configuration allows you to simplify controllers down to
- something like this:
+ This configuration allows you to simplify controllers down to
+ something like this:
+
- @Controller
+ @Controller
@RequestMapping("/users")
public class UserController {
@@ -948,118 +1243,166 @@
}
}
- The PageableArgumentResolver will
- automatically resolve request parameters to build a
- PageRequest instance. By default it will expect
- the following structure for the request parameters:
+
+ The
+ PageableArgumentResolver
+ will
+ automatically resolve request parameters to build a
+ PageRequest
+ instance. By default it will expect
+ the following structure for the request parameters:
+
-
- Request parameters evaluated by
- PageableArgumentResolver
+
+
+ Request parameters evaluated by
+ PageableArgumentResolver
+
-
-
+
+
-
+
-
-
- page
+
+
+
+ page
+
- The page you want to retrieve
-
+ The page you want to retrieve
+
-
- page.size
+
+
+ page.size
+
- The size of the page you want to retrieve
-
+ The size of the page you want to retrieve
+
-
- page.sort
+
+
+ page.sort
+
- The property that should be sorted by
-
+ The property that should be sorted by
+
-
- page.sort.dir
+
+
+ page.sort.dir
+
- The direction that should be used for sorting
-
-
-
-
+ The direction that should be used for sorting
+
+
+
+