简体   繁体   English

JPA Criteria API:遍历列表并创建谓词

[英]JPA Criteria API: Iterate through list and create predicates


I'm trying to migrate an iBatis project into rest service using Spring boot, Spring data JPA and Hibernate.我正在尝试使用 Spring boot、Spring data JPA 和 Hibernate 将 iBatis 项目迁移到休息服务中。 I'm stuck at a query conversion, any help is appreciated.我被困在查询转换中,任何帮助表示赞赏。 This is the iBatis query I'm trying to migrate.这是我尝试迁移的 iBatis 查询。

<foreach item="item" collection="currentStatus">
    <choose>
        <when test="item in fStatusList">
            ((j_status_code != #{item}) AND (f_status_code = #{item}) AND
            (EXP_FLAG IS NULL OR EXP_FLAG ='F' ))
        </when>
        <when test="item in jStatusList">
            ((max_jsc.status_code = #{item}) AND
                <if test="item ==419">
                    EXP_FLAG='H'
                </if>
                <if test="item ==449">
                    EXP_FLAG='C'
                </if>
            </when>
        <otherwise>
            ((j_status_code = #{item}) AND (f_status_code_name is null))
        </otherwise>
    </choose>
</foreach>

This is what I have so far.这是我到目前为止。

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<Job> cq = cb.createQuery(Job.class);
    Root<Job> job = cq.from(Job.class);
    List<Predicate> predicates = new ArrayList<>();
    for (int status : statusList) {
    if (IntStream.of(fStatusList()).anyMatch(x -> x == status)) {
        predicates.add(cb.equal(job.get("f_status_code"), status));
        predicates.add(
            cb.or(
                cb.isNull(job.get("EXP_FLAG")),
                cb.equal(
                    job.get("EXP_FLAG"),"F")));
      } else if (IntStream.of(jStatusList()).anyMatch(x -> x == status)) {
        predicates.add(cb.equal(job.get("jobStatusCode"), status));
        if (status == 10) {
          predicates.add(
              cb.equal(
                  job.get("EXP_FLAG"), "H"));
        } else if (status == 15) {
          predicates.add(
              cb.equal(
                  job.get("EXP_FLAG"), "C"));
        }
      } else {
        predicates.add(
            cb.and(
                cb.isNull(job.get("f_status_code")),
                cb.equal(job.get("j_status_code"), status)));
      }
}
    cq.where(predicates.toArray(new Predicate[0]));
    TypedQuery<Job> query = entityManager.createQuery(cq);

The problem is that the where condition is getting formed like below.问题是 where 条件正在形成,如下所示。 The iteration needs to add OR condition, instead of AND for every statuses.迭代需要为每个状态添加 OR 条件,而不是 AND。 How can I achieve this ?我怎样才能做到这一点?

where
 (
 job0_.f_status_code is null
 ) 
 and job0_.j_status_code=315 
 and job0_.j_status_code=449 
 and job0_.exp_flag=?

Also please advise if using JPA Criteria API is the best option in these scenarios.另外请告知在这些情况下使用 JPA Criteria API 是否是最佳选择。 It seemed pretty complicated and unreadable for some simple iBatis conditions.对于一些简单的 iBatis 条件,它看起来相当复杂和不可读。 Is there a better alternative while using Hibernate ?使用 Hibernate 时有更好的选择吗?

CriteriaQuery#where() creates a conjunction when passed an array of predicates, ie it uses and operator between them. CriteriaQuery#where()在传递一个谓词数组时创建一个连接,即它在它们之间使用and运算符。 If you want to use disjunction, ie the or operator, simply wrap them with CriteriaBuilder#or() :如果你想使用析取,即or运算符,只需用CriteriaBuilder#or()将它们包装起来:

cq.where(cb.or(predicates.toArray(new Predicate[] {})));

In regards to your second question, consider that Hibernate Criteria has been deprecated in favour of JPA Criteria API: Deprecated createCriteria method in Hibernate 5关于您的第二个问题,请考虑 Hibernate Criteria 已被弃用,而支持 JPA Criteria API: 已弃用 Hibernate 5 中的 createCriteria 方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM