1.简述
本文将简单说明拓展接口遇到的一些问题以及如何实现该拓展。
2.JpaRepository
在日常的jpa使用中,我们最常用的就是继承 JpaRepository<T,ID>
,从而实现 jpa
的基本接口应用,示例代码如下:
@Repository
public interface xxxxxxRepository extends JpaRepository<xxxxEntity, xxx> {}
但是如果需要拓展接口,实现更复杂的功能,那么这个就不管用啦,需要进一步的实现。随着我们的代码跟踪,我们发现,JpaRepository
仅仅是接口,往后有着更加复杂的实现类,那就是SimpleJpaRepository<T, ID>
,里边有着大量可用的实现类,可以大大方便我们自己的拓展,后续我就会用到。
3.创建类和继承存储库工厂
为什么要创建存储库工厂呢,如果只是简单的写接口,你会发现其根本扫描不到你的写的类,因为 JpaRepository
再创建容器的时候就已经注入到容器中啦,所以我们需要跟着他们一起注册才能使用,示例代码如下:
//自定义BaseRepositoryFactoryBean,继承JpaRepositoryFactoryBean
public class BaseRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T, S, ID> {
public BaseRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
super(repositoryInterface);
}
//重写createRepositoryFactory方法,用当前的CustomRepositoryFactory创建实例
@Override
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new CustomRepositoryFactory(entityManager);
}
//创建内部类CustomRepositoryFactory,并继承JpaRepositoryFactory
private static class CustomRepositoryFactory<T, ID extends Serializable> extends JpaRepositoryFactory {
public CustomRepositoryFactory(EntityManager entityManager) {
super(entityManager);
}
//重写getTargetRepository方法,获得当前自定义的Repository实现
@Override
protected SimpleJpaRepository<?, ?> getTargetRepository(RepositoryInformation information, EntityManager entityManager) {
return new xxxxxxImpl<T,ID>((Class<T>) information.getDomainType(), entityManager);
}
//重写getRepositoryBaseClass,获得当前自定义的Repository实现的类型
@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return xxxxxxImpl.class;
}
}
}
4.启用 jpa 存储库的注解
实现上述的代码之后,就可以开启注解啦
@EnableJpaRepositories(repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class)
public class RcsApplication {}
5.实现 jpa 的拓展类
既然已经完成上诉 3 中的流程创建,那么我就可以开始编写其中引用的类啦
- 实现类方法如下
public class xxxxImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements xxxx<T, ID> {
final Logger logger = LoggerFactory.getLogger(xxxxImpl.class);
public xxxxImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
}
public xxxxImpl(Class<T> domainClass, EntityManager em) {
super(domainClass, em);
}
/**
* 定义复杂查询的jpa
* @param t 泛型
* @param pageable 分页
* @return 返回查询的分页数据
*/
@Override
public Page<T> find(T t, Pageable pageable) {
}
}
- 接口
@NoRepositoryBean
public interface xxxx<G, ID extends Serializable> extends JpaRepository<G, ID>, JpaSpecificationExecutor<G> {
Page<G> find(G t, Pageable pageable);
}
- 遇到的问题
当我不继承JpaRepository
的话,还是会报无法找到接口类的问题,如果有知道什么原因的,可以和我说一下。
6.使用接口
只需在 jpa
中继承就可以啦
@Repository
public interface TestRepository extends xxxx<TestEntity, Long> {
@Override
Page<TestEntity> find(TestEntity t, Pageable pageable);
}