【问题标题】:How to formulate a JOIN in a typed query?如何在类型化查询中制定 JOIN?
【发布时间】:2013-09-05 14:29:53
【问题描述】:

我想创建一个类型化的查询。

TypedQuery<PubThread> query = em.createQuery(queryString, PubThread.class);
query.setParameter("threadId", threadId);
List<PubThread> otherPubThreads = query.getResultList();

queryString中是如下SQL(目前没有param和静态选择值)

SELECT pt2 FROM pubthread pt2   
JOIN pub_pubthread ppt2 ON pt2.id = ppt2.pubThreads_id  
JOIN pub p2 ON ppt2.pups_id = p2.id     
JOIN pubcategory pc2 ON p2.pubCategoryId = pc2.id   
WHERE pt2.id != 1 and EXISTS (      
    SELECT DISTINCT(pt.id) 
    FROM pubthread pt       
    JOIN pub_pubthread ppt ON pt.id = ppt.pubThreads_id         
    JOIN pub p ON ppt.pups_id = p.id        
    JOIN pubcategory pc ON p.pubCategoryId = pc.id      
    WHERE pc2.id = pc.id and pt.id = 1  
)

如果我将字符串限制为一个简单的选择:SELECT Distinct(pt2.id), pt2.name FROM pubthread pt2,它确实有效。一旦我向它添加一条 JOIN 行,它就会抱怨。如何在 JPA 中正确查询 JOINS?错误是: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ON near line 1, column 81 [SELECT pt2 FROM com.brayan.webapp.model.PubThread pt2 JOIN pub_pubthread ppt2 ON pt2.id = ppt2.pubThreads_id ]

毫无疑问,条件查询会更好。我接受它作为解决方案空间的一部分。

【问题讨论】:

  • 为什么在exists中包含的子查询中使用DISTINCT?没有它会更快。

标签: java sql jpa-2.0


【解决方案1】:

知道了。请参阅下面的完整连接示例。它包括:

  • 多个连接(连接链)
  • 子查询
  • 连接表上的谓词相关/等式,而不是根表。

我还为其他人评论了过时的代码行,看看这是什么错误的方法。

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); CriteriaQuery mainQuery = criteriaBuilder .createQuery(PubThread.class);

    // 1) MainQuery
    // Create the FROM
    Root<PubThread> rootPubThread = mainQuery.from(PubThread.class);
    // Create the JOIN from the first select: join-chaining. You only need the return for ordering. e.g. cq.orderBy(cb.asc(categoryJoin.get(Pub_.title)));
    Join<Pub, PubCategory> categoryJoin = rootPubThread.join(PubThread_.pups).join(Pub_.pubCategory);
    // Create the WHERE
    mainQuery.where(criteriaBuilder.not(criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId)));
    // Create the SELECT, at last
    mainQuery.select(rootPubThread).distinct(true);

    // 2) Subquery
    Subquery<PubThread> subquery = mainQuery.subquery(PubThread.class); 
    Root<PubThread> rootPubThreadSub = subquery.from(PubThread.class); 
    //subquery.where(criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId));
    Join<Pub, PubCategory> categoryJoinSub = rootPubThreadSub.join(PubThread_.pups).join(Pub_.pubCategory);
    subquery.select(rootPubThreadSub);

    //Predicate correlatePredicate = criteriaBuilder.equal(rootPubThreadSub.get(PubThread_.id), rootPubThread);
    Predicate correlatePredicate = criteriaBuilder.and(
            //criteriaBuilder.equal(rootPubThreadSub.get(PubThread_.id), rootPubThread),
            criteriaBuilder.equal(categoryJoinSub.get(PubCategory_.id), categoryJoin.get(PubCategory_.id)),

            criteriaBuilder.equal(rootPubThreadSub.get(PubThread_.id), threadId)
            );
    subquery.where(correlatePredicate);     

    //Predicate correlatePredicate = criteriaBuilder.equal(rootPubThreadSub.get(PubThread_.id), rootPubThread);
    Predicate mainPredicate = criteriaBuilder.and(
            criteriaBuilder.not(criteriaBuilder.equal(rootPubThread.get(PubThread_.id), threadId)),
            criteriaBuilder.exists(subquery)
            );
    //cq.where(criteriaBuilder.exists(subquery));
    mainQuery.where(mainPredicate);

【讨论】:

    【解决方案2】:

    当您调用 createQuery 时,您必须编写 HQL 而不是 SQL(您的 queryString 不是 HQL)。
    在 HQL 中,您必须根据映射实体连接对象。
    如果您还需要 SQL 查询,请使用 createNativeQuery 方法。
    有关如何创建 HQL 查询,请参阅 documentation

    【讨论】:

    • 嗨,Alex,是的,我知道(这就是为什么我将 pt2 放在第一行的投影中)。但是,您是对的,我当然不熟悉用 HQL 编写 JOIN。还;我需要输入查询。条件查询会更好。
    • 好的,我继续使用 JPA Critera Queries。 docs.oracle.com/javaee/6/tutorial/doc/gjivm.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 2017-06-08
    • 2021-03-26
    • 2011-02-14
    相关资源
    最近更新 更多