SpringDataJpa扩展

前言:
SpringDataJpa是SpringData的子框架,在Jpa的基础上进一步进行了封装和扩展,但是依旧满足不了我们的开发需求,因为小编这里列举一下通过自定义Repository对SpringDataJpa的进行扩展,并实现三个功能,如果还需要进行扩展直接添加对应的方法即可。

好了,先放一张图片便于理解吧
SpringDataJpa扩展_第1张图片通过上图可以知道,只要自定义的仓库类实现了JpaRepository,Spring就会代理这个类,完成所有的功能。
在Spring中默认使用的是SimpleJpaRepository作为自定义仓库的实现类 ,但是现在我们需要告诉Spring不要给我们创建实现类,由我们自己定义实现类,然后我们就可以在自定义的实现类中扩展实现自己的功能了。

扩展步骤实现:
  • 1、在仓库包下面自定义一个父仓库类(BaseRepository),继承JpaRepository和JpaSpecificationExecutor
    == 注意这里需要添加注解@NoRepositoryBean,目的就是为了告诉Spring,不要给我这个类创建实现类,我们自己定义实现类==
    注意父接口的泛型
/**
 * 自定义一个Repository,它是JpaRepository的功能基础上继承增强
 * 在上面添加@NoRepositoryBean标注,这样Spring Data Jpa在启动时就不会去实例化BaseRepository这个接口
 * @param 
 * @param 
 */
@NoRepositoryBean    //不需要SpringDataJpa实现此接口,因为需要自己实现此接口,完成功能
public interface BaseRepository extends JpaRepository, JpaSpecificationExecutor {
//以下就是我自己扩展的功能
    //根据Query对象进行查询(高级查询+分页)
    Page findPageByQuery(BaseQuery baseQuery);

    //根据Query对象查询(高级查询不分页)
    List findByQuery(BaseQuery baseQuery);

    //根据自定义jpql与对应的参数进行查询,此处使用可变参数,是因为不知道需要条件有多少
    List findByJpql(String jpql,Object... values);
}
  • 2、自定义父仓库类,去实现父接口,并继承SimpleJpaRepository,此时就可以自己写扩展的方法的逻辑代码了
    注意:此时实现类不要新建包,直接建在当前包下即可,否则整个Spring会无法扫描成功
/**
 * 实现父类中的三个方法
 * @param 
 * @param 
 */
public class BaseRepositoryImpl extends SimpleJpaRepository implements BaseRepository {

    //注意导入的是:import javax.persistence.EntityManager;
    private final EntityManager entityManager;

    //必需要实现父类的这个构造器
    public BaseRepositoryImpl(Class 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 page = super.findAll(spec, pageable);
        return page;
    }

    @Override
    public List 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, S, ID extends Serializable> extends JpaRepositoryFactoryBean {

    @Override
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
        return new MyRepositoryFactory(entityManager); //注:这里创建是我们的自定义类
    }

    //继承JpaRepositoryFactory后,把返回的对象修改成我们自己的实现
    private static  class MyRepositoryFactory   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((Class)information.getDomainType(),entityManager);
        }
        //确定功能对象的类型
        @Override
        protected Class getRepositoryBaseClass(RepositoryMetadata metadata) {
            return BaseRepositoryImpl.class;
        }
    }

}
  • 4、在Spring的xml文件内配置新建的工厂类(BaseRepositoryFactoryBean),告诉SpringDataJpa我的工厂类,如果没有配置的话,SpringDataJpa就会默认去找JpaRepositoryFactory,但是配置了之后,就会找我自定义的工厂。

    
  • 5、到此时,就可以自定义仓库类去继承我的父仓库类(BaseRepository),整个SpingDataJpa的扩展就完成了,然后就可以欢快的使用自己扩展的方法了

你可能感兴趣的:(aisell)