Spring Data JPA 全局DAO的扩展

前几天看了springside4的mini-web代码发现确实有不少新的东东,咱这次单说说Spring Data JPA吧。

引用springside4的 wiki关于对Spring Data JPA的简介

Spring Data JPA在JPA上又做了一层封装,只要编写接口就够了,不用写一行实现代码,CRUD方法啦,分页啦,自动将findByLoginName()的方法定义翻译成适当的QL啦都由它包了:

public interface UserDao extends PagingAndSortingRepository<User, Long> {
User findByLoginName(String loginName);
}
使用上很简单,快速浏览一下下面的资料就够了。

只有一个坑爹的地方,如果要为UserDao扩展方法(而不是接口),要新增一个UserDaoCustom接口,这时候,实现类的名字必须是UserDaoImpl,而不是UserDaoCustomImpl。

另外,除了智能地翻译连Less,Not,And,Or都支持的方法名,它当然也可以直接用@Query在方法上标注复杂的查询语句。

资料
官方文档

使用 Spring Data JPA 简化 JPA 开发 IBM DW上的中文版教程.

如果看完上面的资料 也许你对Spring Data JPA有了初步的认识,动动手你就知道他的强大,但是对DAO的扩展上有点麻烦,上面红字部分是对单个dao进行扩展的方法。下面我们来说一下对全局DAO的扩展,创建你自己的CustomRepository。

首先咱们要建一个自己的扩展接口类MyRepository

Java代码
  1. importjava.io.Serializable;
  2. importorg.springframework.data.jpa.repository.JpaRepository;
  3. publicinterfaceMyRepository<T,IDextendsSerializable>
  4. extendsJpaRepository<T,ID>{
  5. StringsharedCustomMethod();
  6. }
[java] view plain copy
  1. importjava.io.Serializable;
  2. importorg.springframework.data.jpa.repository.JpaRepository;
  3. publicinterfaceMyRepository<T,IDextendsSerializable>
  4. extendsJpaRepository<T,ID>{
  5. StringsharedCustomMethod();
  6. }

其中sharedCustomMethod是全局的共享自定义方法。

然后在建一个实现类MyCustomRepository

Java代码
  1. importjava.io.Serializable;
  2. importjavax.persistence.EntityManager;
  3. importorg.springframework.data.jpa.repository.support.JpaEntityInformation;
  4. importorg.springframework.data.jpa.repository.support.SimpleJpaRepository;
  5. importorg.springframework.data.repository.NoRepositoryBean;
  6. @NoRepositoryBean
  7. publicclassMyCustomRepository<T,IDextendsSerializable>
  8. extendsSimpleJpaRepository<T,ID>implementsMyRepository<T,ID>{
  9. privatefinalEntityManagerentityManager;
  10. publicMyCustomRepository(Class<T>domainClass,EntityManagerem){
  11. super(domainClass,em);
  12. //TODOAuto-generatedconstructorstub
  13. entityManager=em;
  14. }
  15. publicMyCustomRepository(finalJpaEntityInformation<T,?>entityInformation,finalEntityManagerentityManager){
  16. super(entityInformation,entityManager);
  17. this.entityManager=entityManager;
  18. }
  19. publicStringsharedCustomMethod(){
  20. return"hellosharedCustomMethod";
  21. //implementationgoeshere
  22. }
  23. }
[java] view plain copy
  1. importjava.io.Serializable;
  2. importjavax.persistence.EntityManager;
  3. importorg.springframework.data.jpa.repository.support.JpaEntityInformation;
  4. importorg.springframework.data.jpa.repository.support.SimpleJpaRepository;
  5. importorg.springframework.data.repository.NoRepositoryBean;
  6. @NoRepositoryBean
  7. publicclassMyCustomRepository<T,IDextendsSerializable>
  8. extendsSimpleJpaRepository<T,ID>implementsMyRepository<T,ID>{
  9. privatefinalEntityManagerentityManager;
  10. publicMyCustomRepository(Class<T>domainClass,EntityManagerem){
  11. super(domainClass,em);
  12. //TODOAuto-generatedconstructorstub
  13. entityManager=em;
  14. }
  15. publicMyCustomRepository(finalJpaEntityInformation<T,?>entityInformation,finalEntityManagerentityManager){
  16. super(entityInformation,entityManager);
  17. this.entityManager=entityManager;
  18. }
  19. publicStringsharedCustomMethod(){
  20. return"hellosharedCustomMethod";
  21. //implementationgoeshere
  22. }
  23. }

注意 @NoRepositoryBean一定要有的,还有全局的扩展实现类不要用Imp作为后缀名,不然会报异常的(目前还没搞清楚报异常的具体原因,个人猜测可能是和局部的扩展有冲突吧)。

然后在定义MyRepositoryFactory

Java代码
  1. importjava.io.Serializable;
  2. importstaticorg.mockito.Mockito.*;
  3. importjavax.persistence.EntityManager;
  4. importorg.springframework.data.jpa.repository.JpaRepository;
  5. importorg.springframework.data.jpa.repository.support.JpaEntityInformation;
  6. importorg.springframework.data.jpa.repository.support.JpaRepositoryFactory;
  7. importorg.springframework.data.repository.core.RepositoryMetadata;
  8. publicclassMyRepositoryFactoryextendsJpaRepositoryFactory{
  9. publicMyRepositoryFactory(EntityManagerentityManager){
  10. super(entityManager);
  11. //TODOAuto-generatedconstructorstub
  12. }
  13. @Override
  14. @SuppressWarnings("unchecked")
  15. protectedJpaRepository<?,?>getTargetRepository(RepositoryMetadatametadata,EntityManagerem){
  16. JpaEntityInformation<Object,Serializable>entityMetadata=mock(JpaEntityInformation.class);
  17. when(entityMetadata.getJavaType()).thenReturn((Class<Object>)metadata.getDomainType());
  18. returnnewMyCustomRepository<Object,Serializable>(entityMetadata,em);
  19. }
  20. /*
  21. *(non-Javadoc)
  22. *
  23. *@see
  24. *org.springframework.data.repository.support.RepositoryFactorySupport#
  25. *getRepositoryBaseClass()
  26. */
  27. @Override
  28. protectedClass<?>getRepositoryBaseClass(RepositoryMetadatametadata){
  29. returnMyCustomRepository.class;
  30. }
  31. }
[java] view plain copy
  1. importjava.io.Serializable;
  2. importstaticorg.mockito.Mockito.*;
  3. importjavax.persistence.EntityManager;
  4. importorg.springframework.data.jpa.repository.JpaRepository;
  5. importorg.springframework.data.jpa.repository.support.JpaEntityInformation;
  6. importorg.springframework.data.jpa.repository.support.JpaRepositoryFactory;
  7. importorg.springframework.data.repository.core.RepositoryMetadata;
  8. publicclassMyRepositoryFactoryextendsJpaRepositoryFactory{
  9. publicMyRepositoryFactory(EntityManagerentityManager){
  10. super(entityManager);
  11. //TODOAuto-generatedconstructorstub
  12. }
  13. @Override
  14. @SuppressWarnings("unchecked")
  15. protectedJpaRepository<?,?>getTargetRepository(RepositoryMetadatametadata,EntityManagerem){
  16. JpaEntityInformation<Object,Serializable>entityMetadata=mock(JpaEntityInformation.class);
  17. when(entityMetadata.getJavaType()).thenReturn((Class<Object>)metadata.getDomainType());
  18. returnnewMyCustomRepository<Object,Serializable>(entityMetadata,em);
  19. }
  20. /*
  21. *(non-Javadoc)
  22. *
  23. *@see
  24. *org.springframework.data.repository.support.RepositoryFactorySupport#
  25. *getRepositoryBaseClass()
  26. */
  27. @Override
  28. protectedClass<?>getRepositoryBaseClass(RepositoryMetadatametadata){
  29. returnMyCustomRepository.class;
  30. }
  31. }

接着在建一个MyRepositoryFactoryBean

Java代码
  1. importjava.io.Serializable;
  2. importjavax.persistence.EntityManager;
  3. importorg.springframework.data.jpa.repository.JpaRepository;
  4. importorg.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
  5. importorg.springframework.data.repository.core.support.RepositoryFactorySupport;
  6. publicclassMyRepositoryFactoryBean<TextendsJpaRepository<Object,Serializable>>extendsJpaRepositoryFactoryBean<T,Object,Serializable>{
  7. @Override
  8. protectedRepositoryFactorySupportcreateRepositoryFactory(EntityManagerem){
  9. returnnewMyRepositoryFactory(em);
  10. }
  11. }
[java] view plain copy
  1. importjava.io.Serializable;
  2. importjavax.persistence.EntityManager;
  3. importorg.springframework.data.jpa.repository.JpaRepository;
  4. importorg.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
  5. importorg.springframework.data.repository.core.support.RepositoryFactorySupport;
  6. publicclassMyRepositoryFactoryBean<TextendsJpaRepository<Object,Serializable>>extendsJpaRepositoryFactoryBean<T,Object,Serializable>{
  7. @Override
  8. protectedRepositoryFactorySupportcreateRepositoryFactory(EntityManagerem){
  9. returnnewMyRepositoryFactory(em);
  10. }
  11. }


最后在配置文件里需要定义

<jpa:repositories base-package="org.springside.examples.miniweb" transaction-manager-ref="transactionManager"

factory-class="org.springside.examples.miniweb.dao.account.MyRepositoryFactoryBean"

entity-manager-factory-ref="entityManagerFactory"/>

其实这里还有个repository-impl-postfix=" "个人理解他是来定义局部扩展库的实现类的后缀的默认是Imp。

呵呵 这样你就可以使用全局的自定义扩展库了。

你可能感兴趣的:(spring)