你真的了解SpringDataJpa吗?不懂的看这里

SpringDataJpa底层原理分析及扩展

1、什么是Spring Data Jpa?

1.1SpringDataJpa的认识

在了解SpringDataJpa之前,我们先了解一下什么是ORM,和JPA规范。

ORM是指对象关系映射,是关系型数据库到实体对象之间的映射,直白一点将,就是数据库中的表与我们实体类之间的映射关系。

JPA是Java Persistence API的简称,中文名Java持久层API,是关系表的映射关系,并将运行期的实体对象持久化到数据库中。

JPA的实现思想就是ORM,JPA是一个标准的ORM对象关系映射的规范,所以JPA是sun公司提出的一种持久化规范,而基于ORM思想实现的框架就是JPA规范的具体实现,像Hibernate、TopLink、opanjpa都是JPA框架。
JPA的优点是可以让我们在进行crud的时候是面向对象,操作具体的实体类对象,不在是使用sql和原生jdbc进行crud操作,并且在查询的时候可以通过面向对象jpql查询而不是数据库的查询。

Spring Data Jpa是JPA规范的再次封装抽象,底层还是使用的Hibernate的JPA技术实现。通过Spring Data JPA的封装,我们在进行基础的CRUD操作的时候可以不用再去写方法,只需要实现它提供的接口就可以进行操作了

1.2 SpringDatJpa的底层结构

Spring Data Jpa的结构如下图所示:
在这里插入图片描述核心接口:
JpaRepository接口:实现这个接口我们可以完成CRUD操作,分页排序查询,还有简单查询
JpaSpecificationExecutor:这个接口是对SpringDataJpa的封装,通过这个封装可以完成复杂的查询,对于高级查询,即多条件的组合查询就需要使用这个
主要实现类:
SimpleJpaRepository:这个是对JpaRepository接口的实现,是SpringDataJpa的底层实现类。

2、对SpringDataJpa的扩展

2.1 原理分析:

上面介绍了SpringDataJpa的结构,我们在使用的时候可以只需定义一个到层接口去实现JpaRepository接口,那么就可以使用crud的操作,而SpringDataJpa的底层已经帮我们实现了这些方法,底层使用的实现类就是SimpleJpaRepository类。
如果要扩展SpringDataJpa的功能,就要自定义一个类去继承SimpleJpaRepository类,然后再自定义类中扩展我们需要的功能,然后改变SpringDataJpa底层的实现类,改成我们自定义的类,而不是SimpleJpaRepository类。那么我们就需要搞清楚,SpringDataJpa底层是怎样创建这个实现类,底层其实使用的是代理模式:
RepositoryFactoryBean负责返回一个RepositoryFactory,Spring Data Jpa 将使用RepositoryFactory来创建Repository具体实现----SimpleJpaRepository

2.2 代码实现步骤:

1、自定义一个接口BaseRepository用来继承JpaRepository接口,里面定义我们需要扩展功能的方法,因为是接口,不需要写方法的实现

@NoRepositoryBean  //设置这个不被扫描到
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、自定义一个实现类BaseRepositoryImpl,实现我们上面自定义的接口,然后实现里面的方法,因为其父接口继承了JpaRepository接口,所以我们这个实现类还要先继承SimpleJpaRepository类,就不需要实现JpaRepository接口中的方法,达到扩展功能的目的

public class BaseRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID> implements BaseRepository<T,ID> {
   private final EntityManager entityManager;
   public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
       super(domainClass, em);
       this.entityManager = em;
   }
   //下面实现我们自定义扩展的三个功能
   //1、通过query对象进行分页
   @Override
   public Page findPageByQuery(BaseQuery baseQuery) {
       //第一步拿到高级查询的条件
       Specification spec = baseQuery.getSpec();
       //拿到排序的sort对象
       Sort sort = baseQuery.getSort();
       //第三步:根据拿到的数据进行查询并返回:先创建一个Pageable对象
       Pageable pageable = new PageRequest(baseQuery.getPageCurrentPage(),baseQuery.getPageSize(),sort);
       Page page = this.findAll(spec, pageable);
       return page;
   }
    //2、通过query拿到所有的数据不分页
    @Override
    public List findByQuery(BaseQuery baseQuery) {
        //第一步拿到高级查询的条件
        Specification spec = baseQuery.getSpec();
        //拿到排序的sort对象
        Sort sort = baseQuery.getSort();
        //不分页就直接使用findAll()方法不传入分页对象
        return findAll(spec,sort);
    }

    //3、根据jpql来查询数据
    @Override
    public List findByJpql(String jpql, Object... values) {
        //第一步创建query对象
        Query query = entityManager.createQuery(jpql);
        //然后将可变参数设置进去
        if(values !=null){
            for (int i = 0; i < values.length; i++) {
                //设置参数的时候索引从1开始
                query.setParameter(i+1,values[i]);

            }
        }
        //第三步:返回数据
        return query.getResultList();
    }
}

3、自定义BaseRepositoryFactoryBean用来改变SpringDataJpa底层实现的类,通过createRepositoryFactory()方法改变底层的RepositoryFactory类,然后通过RepositoryFactory我们可以将底层实现类SimpleJpaRepository改成我们之前自定义的实现类BaseRepositoryImpl

public class BaseRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean <T,S,ID> {

    //首先我们要复写createRepositoryFactory这个方法,将底层实现的类改成我们自定义的类
    @Override
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
        return new MyRespositoryFactory<T,ID>(entityManager);//这里创建的是我们自定义的类
    }

    //把返回的对象修改成自定义的MyRespositoryFactory类,要继承JpaRepositoryFactory
    //这是一个内部类---->要提供一个带EntityManager参数的构造方法
    private static class MyRespositoryFactory<T,ID extends Serializable> extends JpaRepositoryFactory{
        private final EntityManager entityManager;

        public MyRespositoryFactory(EntityManager entityManager){
            super(entityManager);
            this.entityManager = entityManager;
        }

        //这里将最后返回的对象修改成我们自定义的实现类--->用来替代SimpleJpaRepository
        @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的配置文件applicationContext.xml中配置一下Spring Data Jpa:通过factory-class将我们自定义的FactoryBean配置进去

<!-- base-package:扫描的包 -->
<jpa:repositories base-package="com.lqq.aisell.dao" transaction-manager-ref="transactionManager"
                  entity-manager-factory-ref="entityManagerFactory"
                  factory-class="com.lqq.aisell.dao.BaseRepositoryFactoryBean"/>

总结:完成上面操作以后,SpringDataJpa的底层实现类就被我们自定义的BaseRepositoryImpl类替代,而不是SimpleJpaRepository,所以后期我们dao层可以直接继承BaseRepository这个接口就可以完成SimpleJpaRepository的功能以外,还可以使用我们自定义扩展的功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值