2013-09-05 23 views
1

我想創建一個類型化的查詢。如何在有類型的查詢中制定JOIN?

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

查詢字符串中執行下面的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 ]

毫無疑問,標準查詢會更好。我接受這是解決方案空間的一部分。

+1

爲什麼在子查詢中使用DISTINCT存在?沒有它,速度會更快。 –

回答

2

明白了。請參閱下面的完整連接示例。它包括:

  • 多個連接(加入-鏈)
  • 子查詢
  • 謂詞相關/方程過連接表,而不是根表的其它。

我也評論了其他人的過時代碼行,看看有什麼錯誤的做法。

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); 
1

當您撥打createQuery時,您必須編寫HQL而不是SQL(您的queryString不是HQL)。
在HQL中,您必須根據您的映射實體來連接對象。
如果你需要SQL查詢,請使用createNativeQuery方法。
請參閱documentation關於如何創建HQL查詢。

+0

嗨,亞歷克斯,是的,我知道(這就是爲什麼我已經把pt2放在第一行的投影中)。然而,你是對的,我當然不熟悉在HQL中編寫JOIN。也;我需要輸入查詢。標準查詢會更好。 – feder

+1

好吧,我用JPA Critera Queries走下去。 http://docs.oracle.com/javaee/6/tutorial/doc/gjivm.html – feder