Spring Boot 中使用 Spring-data-jpa 重写分页接口并实现动态传条件以及排序字段

这篇文章讲的是在spring boot 中使用 spring data jpa 重写接口类 并实现自定义分页查询这里不仅包含了查询条件还包含了多个字段排序,希望给你在开发中带来帮助,这里主要是在原来的分页查询方法上做了封装,可能只满足了部分需求,在后续会说到原生sql怎么做封装。

源码地址   https://github.com/xutang123/wanshun

基本的数据结构

自定义注解Sqlfield定义

@Retention(RetentionPolicy.RUNTIME)
public @interface Sqlfield {
    String name() default "";
}

常量类ConnectionFactory

public class ConnectionFactory {
    /**
     * 字符串对象类型
     * */
    public static final String STRING_TYPE_CLASS = "class com.wanshun.cloud.wanshun.base.op.StringType";
    /**
     * 整型对象类型
     * */
    public static final String NUMER_TYPE_CLASS = "class com.wanshun.cloud.wanshun.base.op.StringType";
    /**
     * 获取对象值”git“头
     * */
    public static final String GET_NAME = "get";
    /**
     * 正序
     * */
    public static final String DESC_TYPE = "DESC";
    /**
     * 倒序
     * */
    public static final String ASC_TYPE = "ASC";
}

枚举类Symbol

public enum Symbol {
    eq,
    greater,
    Less,
    like
}

等于对象类EqClass

public class EqClass {
    public Predicate symbolPunlic(Expression expression, Object object, CriteriaBuilder cb){
        return  cb.equal(expression, object.toString());
    }
}

其他符号的对象类基本类似。

自定义数据类型 NumerType

public class NumerType {
    private Symbol op;
    private Integer value;

    public Symbol getOp() {
        return op;
    }

    public void setOp(Symbol op) {
        this.op = op;
    }

    public Integer getValue() {
        return value;
    }

    public void setValue(Integer value) {
        this.value = value;
    }
}
StringType 的value 为 String 类型

公共分页类 Base

public class Base  implements Serializable{
    /**
     *<p>
     *   分页页码
     *</p>
     * */
    protected int page=0;
    /**
     *<p>
     *   分页每页条数
     *</p>
     * */
    protected int size=20;
    /**
     *<p>
     *  排序对象id:DESC,name,ASC
     *</p>
     * */
    protected String sorting="id:DESC";



    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public String getSorting() {
        return sorting;
    }

    public void setSorting(String sorting) {
        this.sorting = sorting;
    }
}

接口 BaseRepository

@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
    boolean support(String modelType);
    Page<T> getPage(Object obj,Base var2);
}
类 BaseRepositoryFactoryBean
public class BaseRepositoryFactoryBean <R extends JpaRepository<T, ID>, T, ID extends Serializable>
        extends JpaRepositoryFactoryBean<R, T, ID> {
    public BaseRepositoryFactoryBean(Class<? extends R> repositoryInterface) {
        super(repositoryInterface);
    }
    @Override
    protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
        return new MyRepositoryFactory(em);
    }

    private static class MyRepositoryFactory<T, ID extends Serializable> extends JpaRepositoryFactory {

        private final EntityManager em;

        public MyRepositoryFactory(EntityManager em) {
            super(em);
            this.em = em;
        }

        @Override
        protected Object getTargetRepository(RepositoryInformation metadata) {
            return new BaseRepositoryImpl<T, ID>((Class<T>) metadata.getDomainType(), em);
        }

        @Override
        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return BaseRepositoryImpl.class;
        }
    }
}

类 BaseRepositoryImpl

public class BaseRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> {

    private final Class<T> domainClass;

    @PersistenceContext
    protected EntityManager em;

    public BaseRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
        super(domainClass, entityManager);
        this.domainClass = domainClass;
    }

    @Override
    public boolean support(String modelType) {
        return domainClass.getName().equals(modelType);
    }
    /**
     * 自定义分页查询
     * @obj 查询条件对象
     * @var2 分页排序条件对象
     * */
    @Override
    public Page<T> getPage( final Object obj,Base var2) {
        Specification specification=  new Specification<T>() {
            @Override
            public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicate = new ArrayList<>();
                Field[] field = obj.getClass().getDeclaredFields();
               for (int j = 0; j < field.length; j++) { // 遍历所有属性
                    String name = field[j].getName(); //
                    String  thename = name.substring(0, 1).toUpperCase() + name.substring(1); // 将属性的首字符大写,方便构造get,set方法
                    String type = field[j].getGenericType().toString(); // 获取属性的类型
                    try {
                        Class clas = String.class;
                        Symbol tyep = Symbol.eq;
                        Object object = null;
                        if (type.equals(ConnectionFactory.STRING_TYPE_CLASS)) { // 如果type是类类型,则前面包含"class ",后面跟类名
                            Method   m = obj.getClass().getMethod(ConnectionFactory.GET_NAME + thename);
                            StringType value = (StringType) m.invoke(obj); // 调用getter方法获取属性
                            if(value != null) {
                                clas = String.class;
                                tyep = value.getOp();
                                object = value.getValue();
                            }
                        }else if (type.equals(ConnectionFactory.NUMER_TYPE_CLASS)) { // 如果type是类类型,则前面包含"class ",后面跟类名
                            Method   m = obj.getClass().getMethod(ConnectionFactory.GET_NAME + thename);
                            NumerType value = (NumerType) m.invoke(obj); // 调用getter方法获取属性
                            if(value != null) {
                                clas = Integer.class;
                                tyep = value.getOp();
                                object = value.getValue();
                            }
                        }else {
                            Method   m = obj.getClass().getMethod(ConnectionFactory.GET_NAME  + thename);
                            object = m.invoke(obj); // 调用getter方法获取属性
                        }
                        if (object != null && object != "") {
                            Expression expression = root.get(name).as(clas);
                            new PredicateNewClass(expression,object,cb);
                            predicate.add(PredicateNewClass.map.get(tyep));
                        }
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
                Predicate[] pre = new Predicate[predicate.size()];
                return query.where(predicate.toArray(pre)).getRestriction();
            }
        };
        //多属性排序
        List<Sort.Order> list = new ArrayList<>();
        String[] op1 = var2.getSorting().split(",");
        for (String string:op1) {
            String[] op2= string.split(":");
            Sort.Direction direction = Sort.Direction.DESC;
            if(ConnectionFactory.ASC_TYPE.equals(op2[1])){
                direction = Sort.Direction.ASC;
            }
            Sort.Order order = new Sort.Order(direction, op2[0]);
            list.add(order);//每次递增一个属性
        }
        Sort sort = new Sort(list);
        Pageable pageable = new PageRequest(var2.getPage(),var2.getSize(),sort);
        return findAll(specification,pageable);
    }




}

猜你喜欢

转载自blog.csdn.net/weixin_40710048/article/details/81204418
今日推荐