Spring Data JPA: 如何实现自定义方法
Spring Data JPA中通过Repository接口自动实现了基本的ORM层操作,但在很多时候,仅仅基本的方法是不够的。经过对比网上的方法及源码,实现了Repository添加自定义方法的办法。
首先我们来添加一个自定义的接口:
添加BaseRepository接口
BaseRepository继承了JpaRepository、JpaSpecificationExecutor,这样可以保证所有Repository都有基本的增删改查以及条件查询等方法。
在BaseRepository上添加@NoRepositoryBean标注,这样Spring Data Jpa在启动时就不会去实例化BaseRepository这个接口
添加logicDelete(ID id);方法,表示该Repository的逻辑删除功能
@NoRepositoryBean
public interface BaseRepository <T, ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T>
{
T logicDelete(ID id);
}
然后,使所有Repository接口都继承BaseRepository
实现BaseRepository接口
定义好自定义的方法后,我们现在通过一个基本的Repository类来实现该方法:
首先添加BaseRepositoryImpl类,继承SimpleJpaRepository类,使其拥有Jpa Repository的基本方法。
再实现logicDelete方法,其参数是领域对象的类型,将其和domainClass对比,如果相等,则该Repository支持该类型的领域对象:
public class BaseRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID>
implements BaseRepository<T, ID> {
public BaseRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
}
public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
this(JpaEntityInformationSupport.getEntityInformation(domainClass, em), em);
}
private void setDeleteStatus(T entity) {
setStatus(entity, Dictionary.BUSINESS_STATUS_DELETE);
}
@Override
@Transactional(rollbackFor = Throwable.class)
public T logicDelete(ID id) {
T entity = findOne(id);
setDeleteStatus(entity);
return save(entity);
}
}
创建自定义RepositoryFactoryBean
接下来我们来创建一个自定义的RepositoryFactoryBean来代替默认的RepositoryFactoryBean。RepositoryFactoryBean负责返回一个RepositoryFactory,Spring Data Jpa 将使用RepositoryFactory来创建Repository具体实现,这里我们用BaseRepositoryImpl代替SimpleJpaRepository作为Repository接口的实现。这样我们就能够达到为所有Repository添加自定义方法的目的。
public class BaseRepositoryFactoryBean, T, I extends Serializable>
extends JpaRepositoryFactoryBean {
@Override
protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
return new MyRepositoryFactory(em);
}
private static class MyRepositoryFactory extends JpaRepositoryFactory {
private final EntityManager em;
public MyRepositoryFactory(EntityManager em) {
super(em);
this.em = em;
}
@Override
protected Object getTargetRepository(RepositoryInformation information) {
return new BaseRepositoryImpl((Class) information.getDomainType(), em);
}
@Override
protected Class getRepositoryBaseClass(RepositoryMetadata metadata) {
return BaseRepositoryImpl.class;
}
}
}
配置Jpa factory class
最后,我们需要配置Jpa使用我们自定义的BaseRepositoryFactoryBean。Spring支持使用标注进行配置,我们在com.xxx.Application中添加标注@EnableJpaRepositories,repositoryFactoryBeanClass指定Repository的工厂类, basePackages用于配置扫描Repositories所在的package及子package:
@SpringBootApplication
@EnableJpaRepositories(repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class, basePackages ="com.xxx.xxx.repository")
@EnableTransactionManagement
public class Application {
public static void main( String[] args ){
SpringApplication.run(Application.class, args);
}
}
这样我们就为所有Repository添加了自定义的方法。