JPA动态查询封装

Posted 浅夏丶未央

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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);
    }    
}                

 

以上是关于JPA动态查询封装的主要内容,如果未能解决你的问题,请参考以下文章

SpringDataJpa

spring Data jpa 一对多关联 动态查询怎么写

Gradle配置IDEA正常识别JPA Metamodel Generator动态生成的代码

MyBatis高级特性

如何在 JPA 命名查询的 IN 子句中使用动态参数?

Spring Data JPA - 创建动态查询注释