前言:
SpringDataJpa是SpringData的子框架,在Jpa的基础上进一步进行了封装和扩展,但是依旧满足不了我们的开发需求,因为小编这里列举一下通过自定义Repository对SpringDataJpa的进行扩展,并实现三个功能,如果还需要进行扩展直接添加对应的方法即可。
好了,先放一张图片便于理解吧
通过上图可以知道,只要自定义的仓库类实现了JpaRepository,Spring就会代理这个类,完成所有的功能。
在Spring中默认使用的是SimpleJpaRepository作为自定义仓库的实现类 ,但是现在我们需要告诉Spring不要给我们创建实现类,由我们自己定义实现类,然后我们就可以在自定义的实现类中扩展实现自己的功能了。
扩展步骤实现:
- 1、在仓库包下面自定义一个父仓库类(BaseRepository),继承JpaRepository和JpaSpecificationExecutor
== 注意这里需要添加注解@NoRepositoryBean,目的就是为了告诉Spring,不要给我这个类创建实现类,我们自己定义实现类==
注意父接口的泛型
/**
* 自定义一个Repository,它是JpaRepository的功能基础上继承增强
* 在上面添加@NoRepositoryBean标注,这样Spring Data Jpa在启动时就不会去实例化BaseRepository这个接口
* @param <T>
* @param <ID>
*/
@NoRepositoryBean //不需要SpringDataJpa实现此接口,因为需要自己实现此接口,完成功能
public interface BaseRepository<T,ID extends Serializable> extends JpaRepository<T,ID>, JpaSpecificationExecutor<T> {
//以下就是我自己扩展的功能
//根据Query对象进行查询(高级查询+分页)
Page findPageByQuery(BaseQuery baseQuery);
//根据Query对象查询(高级查询不分页)
List<T> findByQuery(BaseQuery baseQuery);
//根据自定义jpql与对应的参数进行查询,此处使用可变参数,是因为不知道需要条件有多少
List findByJpql(String jpql,Object... values);
}
- 2、自定义父仓库类,去实现父接口,并继承SimpleJpaRepository,此时就可以自己写扩展的方法的逻辑代码了
注意:此时实现类不要新建包,直接建在当前包下即可,否则整个Spring会无法扫描成功
/**
* 实现父类中的三个方法
* @param <T>
* @param <ID>
*/
public class BaseRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID> implements BaseRepository<T,ID> {
//注意导入的是:import javax.persistence.EntityManager;
private final EntityManager entityManager;
//必需要实现父类的这个构造器
public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
super(domainClass, em);
this.entityManager = em;
}
@Override
public Page findPageByQuery(BaseQuery baseQuery) {
//第一步:拿到所有高级查询条件
Specification spec = baseQuery.creatSpec();
//第二步:拿到排序的值--> 获取的条件是从子类获取的
Sort sort = baseQuery.createSort();
//第三步:根据条件查询分页数据并且返回
Pageable pageable = new PageRequest(baseQuery.getJpaPage(), baseQuery.getPageSize(),sort);
Page<T> page = super.findAll(spec, pageable);
return page;
}
@Override
public List<T> findByQuery(BaseQuery baseQuery) {
//第一步:拿到所有高级查询条件
Specification spec = baseQuery.creatSpec();
//第二步:拿到排序的值
Sort sort = baseQuery.createSort();
//第三步:拿到数据返回
return findAll(spec, sort);
}
@Override
public List findByJpql(String jpql, Object... values) {
//第一步:创建Query对象
Query query = entityManager.createQuery(jpql);
//第二步:把值设置到Query对象中去
if (values!=null) {
for (int i = 0; i < values.length; i++) {
//因为where的?后面的参数是从1开始的
query.setParameter(i + 1, values[i]);
}
}
//第三步:返回数据
return query.getResultList();
}
}
- 3、然后新建一个BaseRepositoryBean,以下方法可以将自定义的父仓库类作物代理类的父类
mport org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import javax.persistence.EntityManager;
import java.io.Serializable;
public class BaseRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T,S,ID> {
@Override
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
return new MyRepositoryFactory<T,ID>(entityManager); //注:这里创建是我们的自定义类
}
//继承JpaRepositoryFactory后,把返回的对象修改成我们自己的实现
private static class MyRepositoryFactory<T,ID extends Serializable> extends JpaRepositoryFactory {
private final EntityManager entityManager;
/**
* Creates a new {@link JpaRepositoryFactory}.
*
* @param entityManager must not be {@literal null}
*/
public MyRepositoryFactory(EntityManager entityManager) {
super(entityManager);
this.entityManager = entityManager;
}
//这里返回最后的功能对象
@Override
protected Object getTargetRepository(RepositoryInformation information) {
return new BaseRepositoryImpl<T,ID>((Class<T>)information.getDomainType(),entityManager);
}
//确定功能对象的类型
@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return BaseRepositoryImpl.class;
}
}
}
- 4、在Spring的xml文件内配置新建的工厂类(BaseRepositoryFactoryBean),告诉SpringDataJpa我的工厂类,如果没有配置的话,SpringDataJpa就会默认去找JpaRepositoryFactory,但是配置了之后,就会找我自定义的工厂。
<!--SpringDataJpa去扫描repository包
若自定义接口继承了JpaRepository接口,就自动完成CRUD以及分页等功能
-->
<jpa:repositories base-package="cn.lzj.aisell.repository"
entity-manager-factory-ref="entityManagerFactory"
transaction-manager-ref="transactionManager"
factory-class="cn.lzj.aisell.repository.BaseRepositoryFactoryBean"
/>
- 5、到此时,就可以自定义仓库类去继承我的父仓库类(BaseRepository),整个SpingDataJpa的扩展就完成了,然后就可以欢快的使用自己扩展的方法了
今天的文章SpringDataJpa扩展分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/27009.html