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. import java.io.Serializable;   
  2.   
  3. import org.springframework.data.jpa.repository.JpaRepository;   
  4.   
  5. public interface MyRepository<T, ID extends Serializable>    
  6. extends JpaRepository<T, ID> {   
  7.   
  8. String  sharedCustomMethod();   
  9. }  
import java.io.Serializable;

import org.springframework.data.jpa.repository.JpaRepository;

public interface MyRepository<T, ID extends Serializable> 
extends JpaRepository<T, ID> {

String  sharedCustomMethod();
}

 

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

 

然后在建一个实现类MyCustomRepository

Java代码 复制代码 收藏代码
  1. import java.io.Serializable;   
  2.   
  3. import javax.persistence.EntityManager;   
  4.   
  5. import org.springframework.data.jpa.repository.support.JpaEntityInformation;   
  6. import org.springframework.data.jpa.repository.support.SimpleJpaRepository;   
  7. import org.springframework.data.repository.NoRepositoryBean;   
  8.   
  9. @NoRepositoryBean  
  10. public class MyCustomRepository<T, ID extends Serializable>    
  11. extends SimpleJpaRepository<T, ID> implements MyRepository<T, ID> {   
  12.   
  13.        
  14. private final EntityManager entityManager;   
  15.        
  16. public MyCustomRepository(Class<T> domainClass, EntityManager em) {   
  17.         super(domainClass, em);   
  18.         // TODO Auto-generated constructor stub  
  19.            
  20.         entityManager=em;   
  21.     }   
  22.   
  23. public MyCustomRepository(final JpaEntityInformation<T, ?> entityInformation, final EntityManager entityManager) {   
  24.     super(entityInformation, entityManager);   
  25.     this.entityManager = entityManager;   
  26. }   
  27.   
  28.   
  29. public String sharedCustomMethod() {   
  30.     return "hello sharedCustomMethod";   
  31.   // implementation goes here  
  32. }    
  33. }  
import java.io.Serializable;

import javax.persistence.EntityManager;

import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.repository.NoRepositoryBean;

@NoRepositoryBean
public class MyCustomRepository<T, ID extends Serializable> 
extends SimpleJpaRepository<T, ID> implements MyRepository<T, ID> {

	
private final EntityManager entityManager;
	
public MyCustomRepository(Class<T> domainClass, EntityManager em) {
		super(domainClass, em);
		// TODO Auto-generated constructor stub
		
		entityManager=em;
	}

public MyCustomRepository(final JpaEntityInformation<T, ?> entityInformation, final EntityManager entityManager) {
    super(entityInformation, entityManager);
    this.entityManager = entityManager;
}


public String sharedCustomMethod() {
	return "hello sharedCustomMethod";
  // implementation goes here
} 
}

 

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

 

然后在定义MyRepositoryFactory

Java代码 复制代码 收藏代码
  1. import java.io.Serializable;   
  2.   
  3. import static org.mockito.Mockito.*;   
  4.   
  5. import javax.persistence.EntityManager;   
  6.   
  7. import org.springframework.data.jpa.repository.JpaRepository;   
  8. import org.springframework.data.jpa.repository.support.JpaEntityInformation;   
  9. import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;   
  10. import org.springframework.data.repository.core.RepositoryMetadata;   
  11.   
  12.   
  13. public class MyRepositoryFactory extends JpaRepositoryFactory {   
  14.   
  15.     public MyRepositoryFactory(EntityManager entityManager) {   
  16.         super(entityManager);   
  17.         // TODO Auto-generated constructor stub  
  18.     }   
  19.     @Override  
  20.     @SuppressWarnings("unchecked")   
  21.     protected JpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata, EntityManager em) {   
  22.   
  23.         JpaEntityInformation<Object, Serializable> entityMetadata = mock(JpaEntityInformation.class);   
  24.         when(entityMetadata.getJavaType()).thenReturn((Class<Object>) metadata.getDomainType());   
  25.         return new MyCustomRepository<Object, Serializable>(entityMetadata, em);   
  26.     }   
  27.   
  28.     /*  
  29.      * (non-Javadoc)  
  30.      *   
  31.      * @see  
  32.      * org.springframework.data.repository.support.RepositoryFactorySupport# 
  33.      * getRepositoryBaseClass() 
  34.      */  
  35.     @Override  
  36.     protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {   
  37.   
  38.         return MyCustomRepository.class;   
  39.     }   
  40. }  
import java.io.Serializable;

import static org.mockito.Mockito.*;

import javax.persistence.EntityManager;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.repository.core.RepositoryMetadata;


public class MyRepositoryFactory extends JpaRepositoryFactory {

	public MyRepositoryFactory(EntityManager entityManager) {
		super(entityManager);
		// TODO Auto-generated constructor stub
	}
	@Override
	@SuppressWarnings("unchecked")
	protected JpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata, EntityManager em) {

		JpaEntityInformation<Object, Serializable> entityMetadata = mock(JpaEntityInformation.class);
		when(entityMetadata.getJavaType()).thenReturn((Class<Object>) metadata.getDomainType());
		return new MyCustomRepository<Object, Serializable>(entityMetadata, em);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.data.repository.support.RepositoryFactorySupport#
	 * getRepositoryBaseClass()
	 */
	@Override
	protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {

		return MyCustomRepository.class;
	}
}

 

接着在建一个MyRepositoryFactoryBean

Java代码 复制代码 收藏代码
  1. import java.io.Serializable;   
  2.   
  3. import javax.persistence.EntityManager;   
  4.   
  5. import org.springframework.data.jpa.repository.JpaRepository;   
  6. import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;   
  7. import org.springframework.data.repository.core.support.RepositoryFactorySupport;   
  8.   
  9. public class MyRepositoryFactoryBean<T extends JpaRepository<Object, Serializable>> extends JpaRepositoryFactoryBean<T, Object, Serializable> {   
  10.   
  11.        
  12.     @Override  
  13.     protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {   
  14.   
  15.         return new MyRepositoryFactory(em);   
  16.     }   
  17. }  
import java.io.Serializable;

import javax.persistence.EntityManager;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

public class MyRepositoryFactoryBean<T extends JpaRepository<Object, Serializable>> extends JpaRepositoryFactoryBean<T, Object, Serializable> {

	
	@Override
	protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {

		return new MyRepositoryFactory(em);
	}
}

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

<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。

 

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

 

Java代码 复制代码 收藏代码
  1. public interface UserDao extends MyRepository<User, Long> ,JpaSpecificationExecutor<User>{   
  2.   
  3. }  
public interface UserDao extends MyRepository<User, Long> ,JpaSpecificationExecutor<User>{

}

 

 

展开阅读全文
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值