【问题标题】:SQL join to Java Criteria APISQL 连接到 Java Criteria API
【发布时间】:2020-10-30 17:14:27
【问题描述】:

如何在 CriteriaQuery 中编写此 SQL 连接?实体之间没有关系。

from 
Table_A a
  left join Table_B b on b.B_id = a.B_id
  left join Table_C c on c.C_id = a.column_x
  left join Table_C d on d.C_id = a.column_y
  left join Table_K k on k.K_id = a.column_z
  left join Table_F f on f.F_id = a.column_t
  left join Table_V v on v.V_id = a.column_t
                              and v.col_s <= b.col_w
                              and v.col_g >= b.col_w

类似这样的:

    CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
    CriteriaQuery<A> criteriaQuery = criteriaBuilder.createQuery(getClazz());
    Root<A> root = criteriaQuery.from(getClazz());

    Join<B, A> join = root.join(B_.ID)
                           .join(C_.ID);

    CriteriaQuery<A> query = criteriaQuery.select(join);

但我无法确定应该匹配哪一列。

        .join(C_.ID == A_.X) 
        .join(K_.ID == A_.Z) 
        
        .join(V_.ID == A_.t && 
                V_.S <= B_.W && 
                V_.G >= B_.W
        )    
                                   
            

【问题讨论】:

    标签: jpa criteria criteria-api


    【解决方案1】:

    如果实体之间没有关系,对于 CriteriaAPI,您必须将查询建模为好像它们都是根表,并且 where 子句中的条件如下:

    CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
    CriteriaQuery<A> criteriaQuery = criteriaBuilder.createQuery(A.class);
    
    Root<A> rootA = criteriaQuery.from(A.class);
    Root<B> rootB = criteriaQuery.from(B.class);
    Root<C> rootC1 = criteriaQuery.from(C.class);
    Root<C> rootC2 = criteriaQuery.from(C.class);
    Root<K> rootK = criteriaQuery.from(K.class);
    Root<F> rootF = criteriaQuery.from(F.class);
    Root<V> rootV = criteriaQuery.from(V.class);
    
    List<Predicate> predicates = new ArrayList<>();
    predicates.add(criteriaBuilder.equal(rootA.get(A_.bId),rootB.get(B_.bId)));
    predicates.add(criteriaBuilder.equal(rootA.get(A_.columnX),rootC1.get(C_.cId)));
    predicates.add(criteriaBuilder.equal(rootA.get(A_.columnY),rootC2.get(C_.cId)));
    predicates.add(criteriaBuilder.equal(rootA.get(A_.columnZ),rootK.get(K_.kId)));
    predicates.add(criteriaBuilder.equal(rootA.get(A_.columnT),rootF.get(K_.fId)));
    
    predicates.add(
        criteriaBuilder.and(
            criteriaBuilder.equal(rootA.get(A_.columnT),rootV.get(V_.vId)),
            criteriaBuilder.and(
                criteriaBuilder.lessThanOrEqualTo(rootV.get(V_.colS),rootB.get(B_.colW)),
                criteriaBuilder.greaterThanOrEqualTo(rootV.get(V_.colG),rootB.get(B_.colW))
             )
         )
     );
    
    criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));
    

    虽然我的建议是您对实体中的关系进行建模,但由于这使得 N 个笛卡尔积成为 N 根的数量,这是非常不理想的

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-18
      • 2023-04-08
      • 2012-04-09
      • 2011-07-28
      • 2021-02-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多