JPA动态查询的实现

   最近在项目中使用到了spring data,Spring Data是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持map-reduce框架和云计算数据服务。

   Spring提供了repository共我们使用,repository提供了几个诸如:findsave delete等方法来供我们在简单的操作数据库,但是当我们的程序中涉及到很多不确定项目的动态查询的时候,就需要我们动态的组建查询条件,可以使用jpa的Specification来实现,在Specification接口只定义了一个方法:

Predicate toPredicate(Root<T>root, CriteriaQuery<?> query, CriteriaBuilder cb);

1:过滤条件会被应用到SQL语句的FROM子句中。在criteria 查询中,查询条件通过PredicateExpression实例应用到CriteriaQuery对象上。

2:这些条件使用 CriteriaQuery.where 方法应用到CriteriaQuery 对象上

3CriteriaBuilder也作为Predicate实例的工厂,通过调用CriteriaBuilder 的条件方法( equalnotEqual gt gelt lebetweenlike等)创建Predicate对象。

     4:复合的Predicate 语句可以使用CriteriaBuilderand, or andnot 方法构建。

我们可以重写这个方法来实现:

reposity中定义find方法,传入参数类型为Specification

Page<DevType> findAll(Specification<DevType> specification,Pageable pageable);

我们定义一个类Criteria<Object>实现Specification接口,在类中重写方法toPredicate,动态拼接查询条件我在此自定义了一个类sqlMessageList,是一个SqlMessage类的listSqlMessage类中包含查询的类型type,查询的字段名name,查询的值value,具体样例代码如下:

@Override
    public Predicate toPredicate(Root<Object> root, CriteriaQuery<?> query,
                                 CriteriaBuilder cb) {
        if (sqlMessageList.size() != 0) {
            String type1 = sqlMessageList.get(0).getType();
            String name1 = sqlMessageList.get(0).getName();
            String value1 = sqlMessageList.get(0).getValue();
            Path<String> pathName1 = root.get(name1);
            Predicate predicate;
            //根据入参sqlMessageList中type来匹配查询条件
            //eq:等于 lk:模糊查询 neq:不等于 gt:大于
            //lt:小于 lteq:小于等于 gteq:大于等于
            switch (type1) {
                case "eq":
                    predicate = cb.equal(pathName1, value1);
                    break;
                case "lk":
                    value1 = "%" + value1 + "%";
                    predicate = cb.like(pathName1, value1);
                    break;
                case "neq":
                    predicate = cb.notEqual(pathName1, value1);
                    break;
                case "gt":
                    predicate = cb.greaterThan(pathName1, value1);
                    break;
                case "lt":
                    predicate = cb.lessThan(pathName1, value1);
                    break;
                case "lteq":
                    predicate = cb.lessThanOrEqualTo(pathName1, value1);
                    break;
                case "gteq":
                    predicate = cb.greaterThanOrEqualTo(pathName1, value1);
                    break;
                default:
                    predicate = cb.equal(pathName1, value1);
                    break;
            }
            for (int i = 1; i < sqlMessageList.size(); i++) {
                String type = sqlMessageList.get(i).getType();
                String name = sqlMessageList.get(i).getName();
                String value = sqlMessageList.get(i).getValue();
                Path<String> pathName = root.get(name);
                switch (type) {
                    case "eq":
                        predicate = cb.and(cb.equal(pathName, value), predicate);
                        break;
                    case "lk":
                        value = "%" + value + "%";
                        predicate = cb.and(cb.like(pathName, value), predicate);
                        break;
                    case "neq":
                        predicate = cb.and(cb.notEqual(pathName, value), predicate);
                        break;
                    case "gt":
                        predicate = cb.and(cb.greaterThan(pathName, value), predicate);
                        break;
                    case "lt":
                        predicate = cb.and(cb.lessThan(pathName, value), predicate);
                        break;
                    case "lteq":
                        predicate = cb.and(cb.lessThanOrEqualTo(pathName, value), predicate);
                        break;
                    case "gteq":
                        predicate = cb.and(cb.greaterThanOrEqualTo(pathName, value), predicate);
                        break;
                    default:
                        predicate = cb.and(cb.equal(pathName, value), predicate);
                        break;
                }
            }
            query.where(predicate);
        }
        return null;
    }

其中 predicate = cb.and()即实现拼接查询条件,实现查询条件的动态拼接。最终调用CriteriaQuerywhere方法执行查询语句。

当我们在service层中调用repository查询方法findAll时,new一个Criteria<Object>对象并给其sqlMessageList成员初始化后将其作为参数传入findAll方法中即可。



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值