SpringDataJpa扩展

SpringDataJpa扩展前言:SpringDataJpa是SpringData的子框架,在Jpa的基础上进一步进行了封装和扩展,但是依旧满足不了我们的开发需求,因为小编这里列举一下通过自定义Repository对SpringDataJpa的进行扩展,并实现三个功能,如果还需要进行扩展直接添加对应的方法即可。好了,先放一张图片便于理解吧通过上图可以知道,只要自定义的仓库类实现了JpaRepository,Spri…

前言:
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

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注