SQL加入Java Criteria API

问题描述

如何在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
        )    
                                   
            

解决方法

如果实体之间没有关系,则对于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个,这并不是最佳选择