使用Predicate进行多条件查询包含and 、like、关键字搜索等方法

 Specification<DangerInfoPO> spec = new Specification<DangerInfoPO>() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder cb) {
                List<Predicate> list = getAndPredicateList(cb,criteriaQuery,root,dto);

                if(null != dto.getDistrictCode() && dto.getDistrictCode().length > 0) {
                    list.add(cb.and(root.get("districtCode").in(dto.getDistrictCode())));
                }
                Predicate[] p = new Predicate[list.size()];


                criteriaQuery.where(cb.and(list.toArray(p)));

                return criteriaQuery.getRestriction();
            }

        };



private List<Predicate> getAndPredicateList(CriteriaBuilder criteriaBuilder, CriteriaQuery query,Root root,
                                                DangerInfoSearchDTO dto) {
        // 多条件And 查询
        List<Predicate> predicateList = new ArrayList<>();

        if (ArrayUtils.isNotEmpty(dto.getOrgcode())) {
            predicateList.add(root.get(DangerInfoConstants.FIELD_ORG_CODE).in(Arrays.asList(dto.getOrgcode())));
        }

        //多like模糊查询类似于select * from user where name like '%四%' or name like '%五%'

        if (ArrayUtils.isNotEmpty(dto.getDangerTypeCode())) {
            String[] dangerTypeCode = dto.getDangerTypeCode();
            int length = dangerTypeCode.length;
            if (length>0){
                List predicateList1 = new ArrayList();
                Predicate [] p = new Predicate[length];
                for (int i = 0; i <length ; i++) {
                    predicateList1.add(criteriaBuilder.like(root.get(DangerInfoConstants.FIELD_DANGERTYPE_CODE),pattern(dangerTypeCode[i])));
                }
                predicateList1.toArray(p);
                predicateList.add(criteriaBuilder.or(p));
            }

        }

        if (null != dto.getStartTime() && null != dto.getEndTime()) {
            predicateList.add(criteriaBuilder.greaterThanOrEqualTo(root.get(DangerInfoConstants.FIELD_UPDATE_TIME),
                    dto.getStartTime()));
            predicateList.add(criteriaBuilder.lessThanOrEqualTo(root.get(DangerInfoConstants.FIELD_UPDATE_TIME),
                    dto.getEndTime()));
        }
        //加上关键词搜索
        if(StringUtils.isNotBlank(dto.getKeywords())){
            predicateList.add(criteriaBuilder.or(criteriaBuilder.like(root.get(DangerInfoConstants.FIELD_DANGER_NAME),
                    pattern(dto.getKeywords()),ESCAPE),criteriaBuilder.like(root.get(DangerInfoConstants.FIELD_DANGER_ADDRESS),
                    pattern(dto.getKeywords()), ESCAPE)));
        }

        if (ArrayUtils.isNotEmpty(dto.getEngrossArea())) {
            Subquery<DangerInfoPO> areaSq = query.subquery(DangerInfoPO.class);
            Root<DangerInfoPO> aRoot = areaSq.from(DangerInfoPO.class);
            List<Predicate> areaSubList = new ArrayList<>();
            for (BigDecimal[] areaArr : dto.getEngrossArea()) {
                if (ArrayUtils.isNotEmpty(areaArr) && areaArr.length > 1) {
                    if (areaArr[0] != null && areaArr[1] == null) {
                        areaSubList.add(criteriaBuilder.greaterThanOrEqualTo(
                                root.get(DangerInfoConstants.FIELD_ENGROSSAREA), areaArr[0]));
                    } else if (areaArr[0] == null && areaArr[1] != null) {
                        areaSubList.add(criteriaBuilder.lessThanOrEqualTo(
                                root.get(DangerInfoConstants.FIELD_ENGROSSAREA), areaArr[1]));
                    } else {
                        areaSubList.add(criteriaBuilder.between(root.get(DangerInfoConstants.FIELD_ENGROSSAREA),
                                areaArr[0], areaArr[1]));
                    }
                }
            }

            Predicate areaSubPredicate = criteriaBuilder.or(areaSubList.toArray(new Predicate[areaSubList.size()]));
            areaSq.select(aRoot.<DangerInfoPO>get(DangerInfoConstants.FIELD_DANGER_ID)).where(areaSubPredicate);
            predicateList.add(root.get(DangerInfoConstants.FIELD_DANGER_ID).in(areaSq));
        }

        if (ArrayUtils.isNotEmpty(dto.getMaxPersonNum())) {
            Subquery<DangerInfoPO> numSq = query.subquery(DangerInfoPO.class);
            Root<DangerInfoPO> nRoot = numSq.from(DangerInfoPO.class);
            List<Predicate> numSubList = new ArrayList<>();
            for (Integer[] maxPerson : dto.getMaxPersonNum()) {
                if (ArrayUtils.isNotEmpty(maxPerson) && maxPerson.length > 1) {
                    if (maxPerson[0] != null && maxPerson[1] == null) {
                        numSubList.add(criteriaBuilder.greaterThanOrEqualTo(
                                root.get(DangerInfoConstants.FIELD_MAXPERSONNUM), maxPerson[0]));
                    } else if (maxPerson[0] == null && maxPerson[1] != null) {
                        numSubList.add(criteriaBuilder.lessThanOrEqualTo(
                                root.get(DangerInfoConstants.FIELD_MAXPERSONNUM), maxPerson[1]));
                    } else {
                        numSubList.add(criteriaBuilder.between(root.get(DangerInfoConstants.FIELD_MAXPERSONNUM),
                                maxPerson[0], maxPerson[1]));
                    }
                }
            }
            Predicate areaSubPredicate = criteriaBuilder.or(numSubList.toArray(new Predicate[numSubList.size()]));
            numSq.select(nRoot.<DangerInfoPO>get(DangerInfoConstants.FIELD_DANGER_ID)).where(areaSubPredicate);
            predicateList.add(root.get(DangerInfoConstants.FIELD_DANGER_ID).in(numSq));
        }
        return predicateList;
    }

### 回答1: 可以使用JPA的Specification实现三表连接模糊查询,示例代码如下: ``` public Specification<User> fuzzyQuery(String keyword) { return (root, query, cb) -> { Join<User, Order> orderJoin = root.join("orders", JoinType.LEFT); Join<Order, Product> productJoin = orderJoin.join("products", JoinType.LEFT); Predicate predicate = cb.like(root.get("name"), "%" + keyword + "%"); predicate = cb.or(predicate, cb.like(orderJoin.get("orderNo"), "%" + keyword + "%")); predicate = cb.or(predicate, cb.like(productJoin.get("name"), "%" + keyword + "%")); return predicate; }; } ``` 这段代码实现了对User、Order、Product三张表的连接查询,并且可以根据关键字进行模糊查询。其中,root表示User表的根节点,orderJoin表示User表与Order表的连接,productJoin表示Order表与Product表的连接。使用cb.like方法实现模糊查询,最后返回Predicate对象。 ### 回答2: 在使用JPA的Specification实现三表连接模糊查询时,可以按照以下步骤进行操作: 1. 创建实体类:首先创建需要查询的三个实体类,并在实体类中定义三个表之间的关联关系。 2. 继承Specification接口:创建一个自定义的Specification接口,该接口需要继承JpaSpecificationExecutor接口,用于实现Specification的各种查询条件。 3. 实现Specification的方法:在自定义的Specification接口中,实现toPredicate方法,用来设置各种查询条件和连接条件。该方法需要返回一个Predicate对象,该对象将作为查询条件传递给JpaSpecificationExecutor接口。 4. 使用Specification进行查询:在使用JpaRepository时,可以使用Specification对象进行查询。示例代码如下: ```java @Repository public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> { } @Service public class UserService { @Autowired private UserRepository userRepository; public List<User> searchUsers(String keyword) { Specification<User> spec = new Specification<User>() { @Override public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) { Join<User, Order> orderJoin = root.join("orders", JoinType.INNER); Join<Order, Product> productJoin = orderJoin.join("product", JoinType.INNER"); Predicate p1 = cb.like(root.get("name"), "%" + keyword + "%"); Predicate p2 = cb.like(orderJoin.get("orderId"), "%" + keyword + "%"); Predicate p3 = cb.like(productJoin.get("productName"), "%" + keyword + "%"); return cb.or(p1, p2, p3); } }; return userRepository.findAll(spec); } } ``` 在上述示例中,首先使用Specification接口实现了toPredicate方法,在该方法中定义了三个表之间的连接关系和模糊查询的条件。然后在UserService中注入了UserRepository,并使用findAll方法传入Specification对象进行查询操作。 通过以上步骤,我们可以使用JPA的Specification实现三表连接模糊查询,根据需求定义查询条件和连接关系,灵活地查询数据。 ### 回答3: 使用JPA的Specification实现三表连接模糊查询可以通过以下步骤实现: 1.定义三个实体类,分别表示三个表,假设为表A、表B和表C。 2.在每个实体类中定义对应的属性和关联关系,例如表A中有一个外键关联到表B,表B中有一个外键关联到表C。 3.创建一个自定义的Specification类,继承JpaSpecificationExecutor接口,并实现Specification接口。 4.在自定义的Specification类中重写toPredicate方法,通过CriteriaBuilder构建查询条件,使用root进行连接查询和模糊查询。 5.在业务层中调用Specification定义的方法,传入条件参数并调用repository的findAll方法即可实现查询。 示例代码如下: ```java @Entity @Table(name = "table_a") public class TableA { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "name") private String name; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "table_b_id") private TableB tableB; // getters and setters } @Entity @Table(name = "table_b") public class TableB { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "type") private String type; @OneToMany(mappedBy = "tableB", cascade = CascadeType.ALL) private List<TableA> tableAList; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "table_c_id") private TableC tableC; // getters and setters } @Entity @Table(name = "table_c") public class TableC { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "title") private String title; @OneToMany(mappedBy = "tableC", cascade = CascadeType.ALL) private List<TableB> tableBList; // getters and setters } public class MySpecification implements Specification<TableA> { private String keyword; public MySpecification(String keyword) { this.keyword = keyword; } @Override public Predicate toPredicate(Root<TableA> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { Join<TableA, TableB> joinAB = root.join("tableB"); Join<TableB, TableC> joinBC = joinAB.join("tableC"); return criteriaBuilder.or( criteriaBuilder.like(root.get("name"), "%" + keyword + "%"), criteriaBuilder.like(joinAB.get("type"), "%" + keyword + "%"), criteriaBuilder.like(joinBC.get("title"), "%" + keyword + "%") ); } } public class MyService { @Autowired private TableARepository tableARepository; public List<TableA> search(String keyword) { MySpecification specification = new MySpecification(keyword); return tableARepository.findAll(specification); } } ``` 以上示例代码中的TableARepository为自定义的JpaRepository,在其继承的JpaRepository类中已经包含了JpaSpecificationExecutor接口,因此可以直接调用findAll方法并传入自定义的Specification实现类进行查询。在MyService中调用MySpecification定义的方法,并传入查询关键字,即可进行三表连接模糊查询
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值