SpringDataCommons官⽅⽂档学习
Spring Data Commons 官⽅⽂档学习  -by
Version 1.12.6.Release, 2017-07-27
,带格式。
Table of Contents
前⾔
Spring Data Commons project 将core Spring concepts应⽤到了很多关系型和⾮关系型数据存储的解决⽅案开发。
参考⽂档
1. 依赖
由于Spring Data modules不同的开发时间,所以它们⼤多数都有不同的主版本号和⼩版本号。想要到兼容版本的最佳⽅式是依赖Spring Data Release Train BOM,已经提供了兼容版本定义。在Maven项⽬中,
你可以在POM的<dependencyManagement />部分声明该依赖:
例⼦1. 使⽤Spring Data release train BOM
1. <dependencyManagement>
2. <dependencies>
3. <dependency>
4. <groupId>org.springframework.data</groupId>
5. <artifactId>spring-data-releasetrain</artifactId>
6. <version>${release-train}</version>
7. <scope>import</scope>
8. <type>pom</type>
9. </dependency>
10. </dependencies>
11. </dependencyManagement>
当前的release train版本是Ingalls-SR6。该train的名字是按照字母顺序升序的,当前可⽤的版本罗列在这⾥。版本的名字遵循这种格式:${name}-${release},其中release可能是下列之⼀:
BUILD-SNAPSHOT - current snapshots
M1, M2 etc. - milestones
RC1, RC2 etc. - release candidates
RELEASE - GA release
SR1, SR2 etc. - service releases
你可以在我们的到实际使⽤的例⼦。如果是就地(in place)声明Spring Data modules,你可能喜欢这样:
例⼦2. 声明⼀个Spring Data module依赖
1. <dependencies>
2. <dependency>
3. <groupId>org.springframework.data</groupId>
4. <artifactId>spring-data-jpa</artifactId>
5. </dependency>
6. </dependencies>
1.1. 使⽤Spring Boot 进⾏依赖管理
Spring Boot已经为你选择了⾮常新的Spring Data modules版本。如果你想要升级到更新的版本,只需要简单的配置下 property spring-data-releasetrain.version to the ,配置成你想使
⽤的。
1.2. Spring框架
当前版本的Spring Data modules要求Spring框架版本是4.3.10.RELEASE,或更⾼。这些模块,也可能运⾏在⽼版本上⾯,但是,强烈推荐使⽤新的版本。
2. 使⽤Spring Data Repositories
Spring Data repository abstraction的⽬标是明显地减少呆板代码(指加载驱动、创建/关闭链接之类的事情)的数量。
2.1. 核⼼概念
Spring Data repository abstraction的核⼼接⼝是Repository。它使⽤domain class以及domain class的id类型作为类型参数来管理(见接⼝泛型)。该接⼝主要是作为⼀个标记接
⼝,来捕获使⽤的类型,并帮助⽤户来发现继承⾃该接⼝的接⼝。CrudRepository为其管理的entities提供了复杂的CRUD功能。
例⼦ 3. CrudRepository interface
publicinterfaceCrudRepository<T, ID extendsSerializable>extendsRepository<T, ID>{<S extends T> S save(S entity);(1)
T findOne(ID primaryKey);(2)Iterable<T> findAll();(3)Long count();(4)voiddelete(T entity);(5)boolean exists(ID primaryKey);(6)// … more functionality omitted.}
①保存给定的 entity。
②返回通过id查到的entity。
③返回所有的entities。
④返回entities的数量。
⑤删除给定的entity。
⑥根据给定的id判断entity是否存在。
我们也提供了特定持久化技术的抽象,如JpaRepository  or MongoRepository。这些接⼝继承⾃CrudRepository,并暴露出底层持久化技术的能⼒,⽽不仅仅是泛泛的持久化技术接⼝
(如CrudRepository )的能⼒。
基于CrudRepository还有⼀个PagingAndSortingRepository abstraction,添加了分页相关的功能:
例⼦4. PagingAndSortingRepository
publicinterfacePagingAndSortingRepository<T, ID extendsSerializable>extendsCrudRepository<T, ID>{Iterable<T> findAll(Sort sort);Page<T> findAll(Pageable pageable);}
如果你想访问User的第⼆页(每页20条记录),你可以这样做:
PagingAndSortingRepository<User,Long> repository =// … get access to a beanPage<User> users = repository.findAll(newPageRequest(1,20));
除了查询⽅法,还有count和delete查询的衍⽣:
例⼦5. 衍⽣的Count查询
publicinterfaceUserRepositoryextendsCrudRepository<User,Long>{Long countByLastname(String lastname);}
例⼦6. 衍⽣的Delete查询
publicinterfaceUserRepositoryextendsCrudRepository<User,Long>{Long deleteByLastname(String lastname);List<User> removeByLastname(String lastname);}
2.2. Query methods 查询⽅法
标准的CRUD functionality repositories,通常会查询底层数据存储。使⽤Spring Data,只需要以下四个步骤:
1. 声明⼀个接⼝,继承Repository 接⼝或其⼦接⼝,填上entity类型和id类型(主键类型)。
interfacePersonRepositoryextendsRepository<Person,Long>{…}
2. 在该接⼝中声明查询⽅法。
interfacePersonRepositoryextendsRepository<Person,Long>{List<Person> findByLastname(String lastname);}
3. 设置Spring,以创建这些接⼝的代理实例。可以使⽤ :
import org.springframework.fig.EnableJpaRepositories;@EnableJpaRepositoriesclassConfig{}
也可以使⽤ :
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns:jpa="/schema/data/jpa"
/schema/beans/spring-beans.xsd
/schema/data/jpa
/schema/data/jpa/spring-jpa.xsd"><jpa:repositoriesbase-package="positories"/></beans>
该例⼦中使⽤了JPA namespace。如果使⽤其他存储的repository abstraction,你需要切换到相应的namespace,例如使⽤mongodb.来代替 jpa。
还需要注意,JavaConfig没有显式地配置⼀个package。想要⾃定义需要扫描的package,可以使⽤@EnableJpaRepositories(或@EnableMongodbRepositories等)注
解的basePackage属性。
4. 获取注⼊的repository实例,并使⽤它。
publicclassSomeClient{@AutowiredprivatePersonRepository repository;publicvoid doSomething(){List<Person> persons = repository.findByLastname("Matthews");}}
下⾯的章节会详细解释每⼀步。
2.3. 定义repository接⼝
第⼀步,必须定义⼀个特定domain class的repository接⼝。该接⼝必须继承Repository,并填写domain class和ID type。如果你想暴露CRUD methods,可以继承CrudRepository
,⽽⾮Repository。
2.3.1. 微调repository定义
通常,你的repository接⼝会继承Repository、CrudRepository或者PagingAndSortingRepository。或者,如果你不想继承Spring Data interfaces的话,你可以在你的repository接⼝上⾯注
解@RepositoryDefinition。继承CrudRepository会暴露⼀个完整的⽅法集合,可以操作你的entities。如果你只想有选择地暴露⼀些⽅法,可以从CrudRepository中复制
到你的domain repository。
这允许你定义你⾃⼰的abstraction,基于Spring Data Repositories的功能。
例⼦7. 有选择地暴露 CRUD methods
@NoRepositoryBeaninterfaceMyBaseRepository<T, ID extendsSerializable>extendsRepository<T, ID>{
T findOne(ID id);
T save(T entity);}interfaceUserRepositoryextendsMyBaseRepository<User,Long>{User findByEmailAddress(EmailAddress emailAddress);}
在这⾥的第⼀步,你定义了⼀个通⽤的base接⼝,暴露了findOne(…)和save(…)。
注意:别忘了注解 @RepositoryDefinition 。
2.3.2. 多个Spring Data modules情况下使⽤Repositories
在应⽤中仅使⽤⼀个Spring Data module,是⼀件很简单的事,在定义的范围内的所有的repository接⼝都被绑定到这个Spring Data module。然⽽,有时候,应⽤需要使⽤多个
Spring Data module。在这种情况下,就要求⼀个repository定义能够区分出不同的持久化技术。Spring Data会进⼊strict repository configuration mode,因为它会在classpath中
探测到多个repository factories。Strict configuration要求 repository 或 domain class的详细信息,来决定Spring Data module绑定⼀个repository定义:
1. 如果该repository定义继承⾃特定模块的repository( ),那么它就是特定Spring Data module的⼀个有效的候选。
2. 如果该domain class 被注解了特定模块的类注解( ),那么它就是特定Spring Data module的⼀个有效的候选。Spring Data modules接受第三⽅注解 (如 JPA的@Entity),或
者提供⾃⼰的注解如针对 Spring Data MongoDB/Spring Data Elasticsearch的@Document注解。
例⼦ 8. 使⽤特定模块的Repository 定义
interfaceMyRepositoryextendsJpaRepository<User,Long>{}@NoRepositoryBeaninterfaceMyBaseRepository<T, ID extendsSerializable>extendsJpaRepository<T, ID>{…}interfaceUserRepositoryextendsMyBaseRepository<User,Long MyRepository和UserRepository继
承⾃JpaRepository。他们都是Spring Data JPA module的有效的候选。
例⼦ 9. 使⽤泛泛的接⼝进⾏Repository定义
interfaceAmbiguousRepositoryextendsRepository<User,Long>{…}@NoRepositoryBeaninterfaceMyBaseRepository<T, ID extendsSerializable>extendsCrudRepository<T, ID>{…}interfaceAmbiguousUserRepositoryextendsMyBaseRepository AmbiguousRepository和AmbiguousUserRepository分别继承⾃Repository和CrudRepository。单独使⽤时没有问题,但多个模块并存时,就⽆法区分repositories该使⽤哪个模块。
例⼦ 10. 使⽤注解的Domain Classes进⾏Repository定义
interfacePersonRepositoryextendsRepository<Person,Long>{…}@EntitypublicclassPerson{…}interfaceUserRepositoryextendsRepository<User,Long>{…}@DocumentpublicclassUser{…}
PersonRepository引⽤了带有JPA注解@Entity的Person,因此,该repository明显属于 Spring Data JPA。UserRepository使⽤了带有 Spring Data MongoDB’s @Document注解的
User。
例⼦ 11. 使⽤代理混合注解的Domain Classes进⾏Repository定义
interfaceJpaPersonRepositoryextendsRepository<Person,Long>{…}interfaceMongoDBPersonRepositoryextendsRepository<Person,Long>{…}@Entity@DocumentpublicclassPerson{…}
该例⼦,⽰意了⼀个同时带有JPA注解和Spring Data MongoDB注解的domain class。它定义了两个repositories:JpaPersonRepository and MongoDBPersonRepository。⼀个是⽤于
JPA,另⼀个⽤于MongoDB。Spring Data不能区分respositories,这会导致未定义的⾏为!
和是被⽤于 strict repository configuration identify repository candidates for a particular Spring Data module。在同⼀个domain type上使⽤多个持久化技术的注解,是可能在多
个持久化技术之间复⽤domain types,但此时 Spring Data 不再能够决定绑定到repository的唯⼀的module。
区分repositories的最后⼀种⽅式是scoping repository的base packages。 Base packages 定义了扫描repository接⼝的出发点。默认,注解驱动的配置使⽤该配置类所在的
package。是强制填写的。
例⼦ 12. 注解驱动的base packages的配置
@EnableJpaRepositories(basePackages ="positories.jpa")@EnableMongoRepositories(basePackages ="")interfaceConfiguration{}
2.4. 定义查询⽅法
repository代理,有两种⽅式来从⽅法名中获取⼀个特定存储的查询。它可以从⽅法名中直接获取查询,或者,可以通过使⽤⼀个⾃定义的查询。具体可⽤的选项取决于具体的存
储。⽆论什么⽅式,总有⼀种策略来决定创建什么样的实际查询。让我们来看⼀下这些可⽤的选项。
2.4.1. Query 查策略
下⾯的策略对于repository infrastructure来说,可以⽤于解析查询。你可以在namespace中配置该策略,通过query-lookup-strategy attribute (XML);也可以在Enable ${store}
Repositories 注解的queryLookupStrategy attribute中配置(javaConfig)。⼀些策略可能不⽀持特定的数据存储。spring framework是什么框架的
CREATE:试图从查询⽅法名中构建⼀个特定存储的查询。⼀般的⽅法是从⽅法中移除⼀个给定的⼤家熟知的前缀集合,并解析剩余的部分。更多关于query construction的
内容,详见。
USE_DECLARED_QUERY:试图到⼀个声明了的查询,如果不到会抛出异常。改查下可以通过⼀个注解来定义,或者通过其他⼿段声明。查阅特定存储的⽂档,以到
可⽤的选项。如果repository infrastructure在启动期间最终没有到⼀个声明过的查询,就会失败。
CREATE_IF_NOT_FOUND (默认):结合了CREATE和USE_DECLARED_QUERY。
2.4.2. Query 创建
Spring Data repository infrastructure中内置的query builder机制,在repository的entities上构建限制查询(constraining queries )时很有⽤。该机制从⽅法名中脱去了前缀find…
By、read…By、query…By、count…By、以及get…By,并解析剩余的部分。引⼊的语句,可以包含更多表达式,如Distinct。然⽽,第⼀个By扮演了分隔符⾓⾊,标明了实际
criteria 的开始。在⼀个⾮常基础的级别上,你可以定义⼀些条件,并使⽤And和Or来连接它们。
例⼦ 13. 从⽅法名中创建查询
publicinterfacePersonRepositoryextendsRepository<User,Long>{List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress,String lastname);// Enables the distinct flag for the queryList<Person> findDistinctPeopleByLastname 解析⽅法名的具体结果,取决于你要为哪个持久存储创建查询。不过,这⾥有⼀些通⽤的事情需要注意。
表达式通常遍历property,结合操作符(可能连接到⼀起)。你可以使⽤AND和OR拼接。你也可以使⽤诸如Between、LessThan、GreaterThan、Like之类的操作符。不同的
数据存储可能⽀持不同的操作符,所以,最好查阅相关参考⽂档。
⽅法解析器⽀持IgnoreCase flag,可以为单独的 properties设置 (例如,findByLastnameIgnoreCase(…)),也可以为所有的 properties设置 (⼀般是String instances,例如,
findByLastnameAndFirstnameAllIgnoreCase(…))。是否⽀持忽略⼤⼩写,不同的存储可能不同的结果,所以,请查阅相关的参考⽂档。
你可以使⽤静态排序,只需要在⽅法名上追加⼀个OrderBy语句,需要引⽤⼀个property,还要提供排序⽅式 (Asc或Desc)。如果想创建⽀持动态排序的查询,见。
2.4.
3. Property expressions
Property expressions 只能指向被管理entity的直接property,前⾯的例⼦已有体现。在查询创建时间,你已经确定了被解析的property是被管理的domain class的⼀个property。
然⽽,你还可以为嵌套的properties定义现在(constraints)。假定Person有⼀个Address property,该property本⾝还有⼀个ZipCode property。这种情况下,下⾯的⽅法名
List<Person> findByAddressZipCode(ZipCode zipCode);
创建了 property traversal x.address.zipCode。该解析算法,从将整个部分 (AddressZipCode)解释为 property 开始,检查 domain class中是否有那个名字的 property  (uncapitalized)。
如果该算法成功了,它就会使⽤那个property。如果失败了,该算法会按驼峰拆分该部分 - 从右侧开始,拆分成head和tail,然后查head相应的property,在我们的例⼦中就是
AddressZip and Code。如果该算法根据head到了⼀个property,它会拿着tail继续构建下⾯的分⽀,按照前⾯的⽅式拆分tail。如果第⼀个拆分不匹配,算法会将拆分点移动到左
侧 (Address, ZipCode),并继续。
虽然这应该已经⾜够应付⼤多数情况,该算法仍然可能选择出错误的property。假定Person class 也有⼀个addressZip property。该算法会在第⼀次拆分时就匹配,然后选择错误的
property,并最终失败(因为addressZip的类型可能没有code property)。
为了解决这种模糊,你可以在⽅法名中使⽤_,以⼿动地定义遍历点。因此,我们的⽅法名可能是这样的:
List<Person> findByAddress_ZipCode(ZipCode zipCode);
注意:因为我们将下划线_作为保留字符,我们强烈建议⽤户的开发遵守标准Java命名惯例(例如,不在property名字中使⽤下划线,⽽是⽤驼峰代替)。
2.4.4. 特殊参数处理
为了处理在你的查询中的参数,你可以简单地定义⽅法参数,如同上⾯所见到的那样。除此之外,the infrastructure 还可以识别特定的特殊类型,如Pageable and Sort,以动态的
应⽤分页和排序。
例⼦ 14. 在查询⽅法中使⽤Pageable、 Slice 和Sort
Page<User> findByLastname(String lastname,Pageable pageable);Slice<User> findByLastname(String lastname,Pageable pageable);List<User> findByLastname(String lastname,Sort sort);List<User> findByLastname(String lastname 第⼀个⽅法,允许你传⼊⼀个org.springframework.data.domain.Pageable instance,来动态添加分页功能。⼀个Page包含元素的总数量和可⽤的页数。它能这样,是因为 the
infrastructure 触发了⼀个count query,从⽽能够计算总数量。取决于不同的存储,这可能耗费巨⼤,所以可以返回Slice。⼀个Slice仅包括是否有下⼀个可⽤的Slice。
排序选项,也可以通过Pageable instance 处理。如果你只需要排序,那你只需要给你的⽅法添加⼀个org.springframework.data.domain.Sort参数。如你所见,直接返回⼀个List也是可
以的。在这种情况下,构建Page instance所需的元数据就不需要了(就是说不需要额外的count query了),但只能查询给定返回的entities。
2.4.5. 限制查询结果
查询⽅法的结果可以使⽤关键字first或top来限制,这两个可以互换。⼀个可选的数值可以追加到 top/first ,以标明最⼤返回的数量。如果留空,默认是1。
例⼦ 15. L使⽤Top and First限制查询结果
User findFirstByOrderByLastnameAsc();User findTopByOrderByAgeDesc();Page<User> queryFirst10ByLastname(String lastname,Pageable pageable);Slice<User> findTop3ByLastname(String lastname,Pageable pageable);List<User 限制表达式,也⽀持关键字Distinct。另外,也⽀持Optional。
If pagination or slicing is applied to a limiting query pagination (and the calculation of the number of pages available) then it is applied within the limited result.  -- 这句嘛意思?
Note that limiting the results in combination with dynamic sorting via a Sort parameter allows to express query methods for the 'K' smallest as well as for the 'K' biggest
elements.
2.4.6. 流式查询结果
通过使⽤Java 8 Stream<T>作为返回返回类型,查询⽅法的结果可以被加速处理。
例⼦ 16. 使⽤Java 8 Stream<T>处理返回结果
@Query("select u from User u")Stream<User> findAllByCustomQueryAndStream();Stream<User> readAllByFirstnameNotNull();@Query("select u from User u")Stream<User> streamAllPaged(Pageable pageable);
注意:⼀个Stream 底层会封装数据存储的特定资源,因此,必须在使⽤完毕之后关闭。可以使⽤ close() ⼿动关闭,或者也可以使⽤Java 7 try-with-resources 代码块。
例⼦ 17. 在try-with-resources代码块中使⽤Stream<T> result
try(Stream<User> stream = repository.findAllByCustomQueryAndStream()){
stream.forEach(…);}
注意:⽬前,不是所有的Spring Data modules都⽀持Stream<T> 作为返回类型。
2.4.7. 异步查询结果(不翻译了)
Repository queries can be executed asynchronously using . This means the method will return immediately upon invocation and the actual query execution will occur in a task
that has been submitted to a Spring TaskExecutor.
@AsyncFuture<User> findByFirstname(String firstname);(1)@AsyncCompletableFuture<User> findOneByFirstname(String firstname);(2)@AsyncListenableFuture<User> findOneByLastname(String lastname);(3)
①使⽤urrent.Future 作为返回类型。
②使⽤Java 8的urrent.CompletableFuture 作为返回类型。
③使⽤org.urrent.ListenableFuture 作为返回类型。
2.5. 创建 repository instances
在本部分,你会创建定义过的repository接⼝的实例和bean 定义。⼀种⽅式是使⽤ Spring namespace,但我们⼀般都推荐使⽤Java-Config 形式的配置。
2.5.1. XML configuration
每个 Spring Data module 都包含⼀个 repositories element,允许你简单地定义⼀个base package -- Spring会扫描它。
例⼦ 18. 启⽤ Spring Data repositories -- 通过 XML
<?xml version="1.0" encoding="UTF-8"?><beans:beansxmlns:beans="/schema/beans"xmlns:xsi="/2001/XMLSchema-instance"xmlns="/schema/data/jpa"    /schema/beans/spring-beans.xsd
/schema/data/jpa
/schema/data/jpa/spring-jpa.xsd"><repositoriesbase-package="positories"/></beans:beans>
在上⾯的例⼦中,Spring被配置成扫描positories和其所有⼦包,以查所有继承⾃Repository或其⼦接⼝的接⼝。对于每个到的接⼝,infrastructure会注册持久化技
术特定的FactoryBean,以创建恰当的代理,从⽽处理查询⽅法的调⽤。每个bean都被注册了⼀个bean name,默认从接⼝名字中获取,因此⼀个UserRepository接⼝,可能被注册
成userRepository。base-package attribute 允许通配符,所以,你还可以定义⼀个pattern。
使⽤过滤器
默认,the infrastructure会捡起每⼀个继承⾃持久化技术特定的Repository及其⼦接⼝的接⼝ -- 要在base package之下,并创建⼀个bean实例。但是,你或许想要更细化的控制。
这时,你需要使⽤ <repositories /> 中的<include-filter />和<exclude-filter /> elements。详见。
例如,想要排除特定接⼝,你可能会使⽤下⾯的配置:
例⼦ 19. 使⽤ exclude-filter element
<repositoriesbase-package="positories"><context:exclude-filtertype="regex"expression=".*SomeRepository"/></repositories>
该例⼦排除了所有以SomeRepository结尾的内容。
2.5.2. JavaConfig
The repository infrastructure 也可以通过在⼀个JavaConfig class上使⽤@Enable${store}Repositories注解来开启。
下⾯是⼀个简单的例⼦。
例⼦ 20. 样例基于注解的repository configuration
@Configuration@EnableJpaRepositories("positories")classApplicationConfiguration{@BeanpublicEntityManagerFactory entityManagerFactory(){// …}}
该样例,使⽤了JPA特有的注解,你可能会切换成其他的。同样的情况也适⽤于EntityManagerFactory  bean。
2.5.
3. 单独使⽤ Standalone usage
你可以在Spring container之外使⽤ the repository infrastructure,例如,在CDI 环境中。你仍然需要⼀些Spring lib,但⼀般,你也可以通过编码设置repositories。
例⼦ 21. 单独使⽤ repository factory
RepositoryFactorySupport factory =…// Instantiate factory hereUserRepository repository = Repository(UserRepository.class);
2.6. Spring Data repositories的⾃定义实现
经常,需要为⼏个repository⽅法提供⼀个⾃定义的实现。Spring Data repositories允许你提供⾃定义的 repository 代码,并将其集成到 generic CRUD abstraction中。
2.6.1. 为某个repositories 添加⾃定义⾏为
为了丰富⼀个带有⾃定义功能的repository,你需要先定义⼀个接⼝,以及接⼝中⾃定义功能的实现。⽤你的repository 接⼝来继承这个⾃定义的接⼝。
例⼦ 22. ⾃定义repository功能的接⼝
interfaceUserRepositoryCustom{publicvoid someCustomMethod(User user);}
例⼦ 23. ⾃定义repository功能的实现
classUserRepositoryImplimplementsUserRepositoryCustom{publicvoid someCustomMethod(User user){// Your custom implementation}}
注意:这⾥最重要的就是后缀Impl。
该实现,不依赖于 Spring Data,可以作为⼀个常规的 Spring bean。因此,你可以使⽤标准的依赖注⼊⽅式将其注⼊到其他bean中,如 JdbcTemplate。
例⼦ 24. 更改你的基础repository 接⼝
interfaceUserRepositoryextendsCrudRepository<User,Long>,UserRepositoryCustom{// Declare query methods here}
让你的标准的 repository interface继承这个⾃定义的接⼝。
Configuration 配置
如果你使⽤namespace 配置, the repository infrastructure会试着⾃动探测⾃定义的实现,通过扫描base package中的classes。这些classes,需要遵守命名惯例,即在
namespace element的 attribute repository-impl-postfix中设置的。该后缀默认是Impl。
例⼦ 25. 配置例⼦
<repositoriesbase-package="pository"/><repositoriesbase-package="pository"repository-impl-postfix="FooBar"/>
第⼀个配置,会试着查⼀个class:pository.UserRepositoryImpl,将其作为⾃定义的repository 实现;第⼆个配置,则会试着查pository.UserRepositoryFooBar。
Manual wiring ⼿动注⼊(略)
The approach just shown works well if your custom implementation uses annotation-based configuration and autowiring only, as it will be treated as any other Spring bean. If
your custom implementation bean needs special wiring, you simply declare the bean and name it after the conventions just described. The infrastructure will then refer to the
manually defined bean definition by name instead of creating one itself.
Example 26. Manual wiring of custom implementations
<repositoriesbase-package="pository"/><beans:beanid="userRepositoryImpl"class="…"><!-- further configuration --></beans:bean>
2.6.2. 为所有repositories 添加⾃定义⾏为(暂不需要,略)
The preceding approach is not feasible when you want to add a single method to all your repository interfaces. To add custom behavior to all repositories, you first add an
intermediate interface to declare the shared behavior.
Example 27. An interface declaring custom shared behavior
@NoRepositoryBeanpublicinterfaceMyRepository<T, ID extendsSerializable>extendsPagingAndSortingRepository<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. Next, create an
implementation of the intermediate interface that extends the persistence technology-specific repository base class. This class will then act as a custom base class for the
repository proxies.
Example 28. Custom repository base class
publicclassMyRepositoryImpl<T, ID extendsSerializable>extendsSimpleJpaRepository<T, ID>implementsMyRepository<T, ID>{privatefinalEntityManager entityManager;publicMyRepositoryImpl(JpaEntityInformation entityInformation The class needs to have a constructor of the super class which the store-specific repository factory implementation is using. In case the repository base class has multiple constructors, override the one taking an EntityInformation plus a store specific infrastructure object (e.g. an EntityManager or a template class).
The default behavior 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 its 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 that extends Repository from being instantiated as a repository instance, you can either
annotate it with @NoRepositoryBean (as seen above) or move it outside of the configured base-package.
The final step is to make the Spring Data infrastructure aware of the customized repository base class. In JavaConfig this is achieved by using the repositoryBaseClass attribute of
the @Enable…Repositories annotation:
Example 29. Configuring a custom repository base class using JavaConfig
@Configuration@EnableJpaRepositories(repositoryBaseClass =MyRepositoryImpl.class)classApplicationConfiguration{…}
A corresponding attribute is available in the XML namespace.
Example 30. Configuring a custom repository base class using XML
<repositoriesbase-package="pository"base-class="….MyRepositoryImpl"/>

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。