JPA动态查询封装

一、定义一个查询条件容器

/**
 * 定义一个查询条件容器
 *
 * @param <T>
 */
public class Criteria<T> implements Specification<T> {
    private List<Criterion> criterions = new ArrayList<Criterion>();  

    public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
            CriteriaBuilder builder) {
        if (!criterions.isEmpty()) {
            List<Predicate> predicates = new ArrayList<Predicate>();
            for(Criterion c : criterions){
                predicates.add(c.toPredicate(root, query,builder));
            }
            // 将所有条件用 and 联合起来
            if (predicates.size() > 0) {
                return builder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        }
        return builder.conjunction();
    }
    /**
     * 增加简单条件表达式
     * @Methods Name add
     * @param
     */
    public Criteria<T> add(Criterion criterion){  

        if(criterion!=null){
            criterions.add(criterion);
        }

        return this;
    }
}  

二、条件接口

public interface Criterion {  

    public enum Operator {
        EQ, NE, LIKE, GT, LT, GTE, LTE, AND, OR
    }  

    public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
                                 CriteriaBuilder builder);
}  

三、逻辑条件表达式,用于复杂条件时使用,如or或and

public class LogicalExpression implements Criterion {
    private Criterion[] criterion;  // 逻辑表达式中包含的表达式
    private Operator operator;      //计算符  

    public LogicalExpression(Criterion[] criterions, Operator operator) {
        this.criterion = criterions;
        this.operator = operator;
    }  

    public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
            CriteriaBuilder builder) {
        List<Predicate> predicates = new ArrayList<Predicate>();
        for(int i=0;i<this.criterion.length;i++){
            predicates.add(this.criterion[i].toPredicate(root, query, builder));
        }
        switch (operator) {
        case OR:
            return builder.or(predicates.toArray(new Predicate[predicates.size()]));
        case AND:
            return builder.and(predicates.toArray(new Predicate[predicates.size()]));

        default:
            return null;
        }
    }

}  

四、简单条件表达式

public class SimpleExpression implements Criterion{  

    private String fieldName;       //属性名
    private Object value;           //对应值
    private Operator operator;      //计算符  

    protected SimpleExpression(String fieldName, Object value, Operator operator) {
        this.fieldName = fieldName;
        this.value = value;
        this.operator = operator;
    }  

    public String getFieldName() {
        return fieldName;
    }
    public Object getValue() {
        return value;
    }
    public Operator getOperator() {
        return operator;
    }
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
            CriteriaBuilder builder) {
        Path expression = null;
        if(fieldName.contains(".")){
            String[] names = StringUtils.split(fieldName, ".");
            expression = root.get(names[0]);
            for (int i = 1; i < names.length; i++) {
                expression = expression.get(names[i]);
            }
        }else{
            expression = root.get(fieldName);
        }
        switch (operator) {
        case EQ:
            return builder.equal(expression, value);
        case NE:
            return builder.notEqual(expression, value);
        case LIKE:
            return builder.like((Expression<String>) expression, "%" + value + "%");
        case LT:
            return builder.lessThan(expression, (Comparable) value);
        case GT:
            return builder.greaterThan(expression, (Comparable) value);
        case LTE:
            return builder.lessThanOrEqualTo(expression, (Comparable) value);
        case GTE:
            return builder.greaterThanOrEqualTo(expression, (Comparable) value);
        default:
            return null;
        }
    }

}  

五、条件构造器,用于创建条件表达式

public class Restrictions {  

    /**
     * 等于
     * @param fieldName
     * @param value
     * @return
     */
    public static SimpleExpression eq(String fieldName, Object value) {
        if(StringUtils.isEmpty(value))return null;
        return new SimpleExpression (fieldName, value, Criterion.Operator.EQ);
    }  

    /**
     * 不等于
     * @param fieldName
     * @param value
     * @return
     */
    public static SimpleExpression ne(String fieldName, Object value) {
        if(StringUtils.isEmpty(value))return null;
        return new SimpleExpression (fieldName, value, Criterion.Operator.NE);
    }  

    /**
     * 模糊匹配
     * @param fieldName
     * @param value
     * @param
     * @return
     */
    public static SimpleExpression like(String fieldName, String value) {
        if(StringUtils.isEmpty(value))return null;
        return new SimpleExpression (fieldName, value, Criterion.Operator.LIKE);
    }  

    /**
     * 大于
     * @param fieldName
     * @param value
     * @return
     */
    public static SimpleExpression gt(String fieldName, Object value) {
        if(StringUtils.isEmpty(value))return null;
        return new SimpleExpression (fieldName, value, Criterion.Operator.GT);
    }  

    /**
     * 小于
     * @param fieldName
     * @param value
     * @return
     */
    public static SimpleExpression lt(String fieldName, Object value) {
        if(StringUtils.isEmpty(value))return null;
        return new SimpleExpression (fieldName, value, Criterion.Operator.LT);
    }  

    /**
     * 大于等于
     * @param fieldName
     * @param value
     * @return
     */
    public static SimpleExpression lte(String fieldName, Object value) {
        if(StringUtils.isEmpty(value))return null;
        return new SimpleExpression (fieldName, value, Criterion.Operator.LTE);
    }  

    /**
     * 小于等于
     * @param fieldName
     * @param value
     * @param
     * @return
     */
    public static SimpleExpression gte(String fieldName, Object value) {
        if(StringUtils.isEmpty(value))return null;
        return new SimpleExpression (fieldName, value, Criterion.Operator.GTE);
    }  

    /**
     * 并且
     * @param criterions
     * @return
     */
    public static LogicalExpression and(Criterion... criterions){
        return new LogicalExpression(criterions, Criterion.Operator.AND);
    }
    /**
     * 或者
     * @param criterions
     * @return
     */
    public static LogicalExpression or(Criterion... criterions){
        return new LogicalExpression(criterions, Criterion.Operator.OR);
    }
    /**
     * 包含于
     * @param fieldName
     * @param value
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static LogicalExpression in(String fieldName, Collection value, boolean ignoreNull) {
        if(ignoreNull&&(value==null||value.isEmpty())){
            return null;
        }
        SimpleExpression[] ses = new SimpleExpression[value.size()];
        int i=0;
        for(Object obj : value){
            ses[i]=new SimpleExpression(fieldName,obj, Criterion.Operator.EQ);
            i++;
        }
        return new LogicalExpression(ses, Criterion.Operator.OR);
    }

    /**
     * 不包含于
     * @param fieldName
     * @param value
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static LogicalExpression notin(String fieldName, Collection value, boolean ignoreNull) {
        if(ignoreNull&&(value==null||value.isEmpty())){
            return null;
        }
        SimpleExpression[] ses = new SimpleExpression[value.size()];
        int i=0;
        for(Object obj : value){
            ses[i]=new SimpleExpression(fieldName,obj, Criterion.Operator.NE);
            i++;
        }
        return new LogicalExpression(ses, Criterion.Operator.AND);
    }

    /**
     *  between
     * @param fieldName
     * @param object1
     * @param object2
     * @return
     */
    public static LogicalExpression between(String fieldName, Object object1, Object object2)
    {
        if(object1 == null || object2 == null)
        {
            return null;
        }
        SimpleExpression[]ses=new SimpleExpression[2];
        ses[0]=new SimpleExpression(fieldName,object1, Criterion.Operator.GTE);
        ses[1]=new SimpleExpression(fieldName,object2, Criterion.Operator.LTE);
        return new LogicalExpression(ses, Criterion.Operator.AND);
    }

六、构造动态查询仓库接口

public interface BaseRepository<T,ID extends Serializable> extends PagingAndSortingRepository<T,ID> {

    int count(Specification<T> specification);
    Page<T> findAll(Specification<T> specification, Pageable pageable);
    List<T> findAll(Specification<T> specification);
}

使用实例:

POJO对象为

public class UserInfo
{
    private Integer id;
    private String name;
    ...
}

dao接口为

public interface UserInfoService extends BaseRepository<UserInfo,Integer>
{
}

使用:

@RunWith(SpringRunner.class)
@SpringBootTest
public class test
{
    @Autowired
    private UserInfoService userInfoService;
    @Test
    public void test()
    {
           Criteria<UserInfo> criteria = new Criteria<>();
           criteria.add(Restrictions.eq("id",10)).add(Restrictions.like("name","abc"));
           List<UserInfo> users = userInfoService.findAll(criteria);
    }
}                
时间: 2024-10-10 11:05:58

JPA动态查询封装的相关文章

spring data jpa的动态查询封装(转)

最近使用spring data jpa做了两个项目,对于动态查询的不友好做了个类似hibernate的封装,记录也分享下 首先定义一个所有条件的容器,继承Specification Java代码   /** * 定义一个查询条件容器 * @author lee * * @param <T> */ public class Criteria<T> implements Specification<T>{ private List<Criterion> crit

Spring Data JPA动态查询(多条件and)

entity: @Entity @Table(name = "data_illustration") public class Test { @Id @GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator") @GeneratedValue(generator = "uuid") private String id; @Column

spring JPA 动态查询

没什么好说的,记住就行. 下面是在Service中的方法 Page<TStaff> staffs=dao.findAll(new Specification<TStaff>() { @Override public Predicate toPredicate(Root<TStaff> root, CriteriaQuery<?> query, CriteriaBuilder cb) { Predicate predicate = cb.conjunction

spring data jpa封装specification实现简单风格的动态查询

github:https://github.com/peterowang/spring-data-jpa-demo Spring Data JPA已经帮助我们很大程度上简化了我们的查询操作,我们甚至只要写一个接口,然后单纯的写一些方法就可以完成各式各样的查询,但是对于我们程序设计人员而言,总希望所有的查询变得更加的简单方便,为了给程序人员进行再一次的封装,Spring Data JPA提供了Specification的方式进行查询,在前面的内容已经演示过这种查询了,但是,我们在使用的过程中发现这

SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法

首先谢谢大佬的简书文章:http://www.jianshu.com/p/45ad65690e33# 这篇文章中讲的是spring中使用spring data jpa,使用了xml配置文件.我现在使用的是spring boot ,没有了xml文件配置就方便多了.我同样尝试了两种方式,也都是简单的查询,需要更复杂的查询,还需要我研究研究.往下看,需要先配置springboot的开发环境,需要大致了解springboot,这里可以看下面两篇文章: springboot 项目新建 springboot

Hibernate与Jpa的关系,以及使用分页和动态查询

最近由于项目调动,我去了使用JPA的项目组, 因为之前的项目组使用MyBatis,所以一时间关于JPA和Hibernate的知识体系记得不熟,导致出现了混乱:在网上看到了这篇文章,终于解决了我心中的疑惑:JPA是一种规范,Hibernate实现了这种规范 . 这篇短小精悍的文章给了我很多的启发,于是,我把它"复制"到了本文! http://blog.sina.com.cn/s/blog_5f1619e80100yoxz.html 我知道Jpa是一种规范,而Hibernate是它的一种实

linq之InnerJoin和LeftJoin以及封装动态查询条件版本

Linq的出现,使数据集的处理显得愈来愈简便.很多时候对于本地数据集的处理,脑海中的第一反应,即尝试使用Linq来实现.诸如DataTable的innerJoin以及leftJoin等操作,很多时候我们一接到类似的需求,立马便动手,诸如以下demo: 一.InnerJoin 1 var qMyMx = from mxDr in _dtJgTcDetail.Rows.Cast<DataRow>().Where(drMx => id.Equals(drMx["TCID"]

Spring data jpa 实现简单动态查询的通用Specification方法

本篇前提: SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法 这篇文章中的第二种方法 实现Specification 这块的方法 只适用于一个对象针对某一个固定字段查询,下面通过泛型改写了这个方法: import java.util.List; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import j

22 Specifications动态查询

Specifications动态查询 有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在Spring Data JPA中可以通过JpaSpecificationExecutor接口查询.相比JPQL,其优势是类型安全,更加的面向对象. import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageab