2011-09-13 82 views
2

我在JPA中使用QueryDSL。QueryDSL:查詢關係和屬性

我想查詢一個實體的某些屬性,是這樣的:

QPost post = QPost.post; 
JPAQuery q = new JPAQuery(em); 
List<Object[]> rows = q.from(post).where(...).list(post.id, post.name); 

它工作正常。

如果我想查詢關係屬性,例如一個帖子的評論:

List<Set<Comment>> rows = q.from(post).where(...).list(post.comments); 

這也很好。

但是,當我想一起查詢關係和簡單的屬性,例如

List<Object[]> rows = q.from(post).where(...).list(post.id, post.name, post.comments); 

然後出現了一些問題,導致錯誤的SQL語法。

然後我意識到無法在一個SQL語句中一起查詢它們。

QueryDSL是否有可能以某種方式處理關係並生成其他查詢(就像hibernate對懶惰關係所做的一樣),並將結果加載到?

或者我應該只查詢兩次,然後合併兩個結果列表?

P.S.我真正想要的是每個帖子都有它的評論ID。所以一個函數來連接每個帖子的評論id更好,這種expressin可能嗎?

q.list(post.id, post.name, post.comments.all().id.join()) 

,併產生像(select group_concat(c.id) from comments as c inner join post where c.id = post.id)

回答

5

Querydsl JPA子查詢的SQL僅限於JPQL的表現力,所以你所要求的是不可能的Querydsl JPA。你可以嘗試用Querydsl SQL來表達它。它應該是可能的。同樣,因爲你不投影實體,但文字和集合它可能工作得很好。

或者,您可以只加載註釋ID加載帖子,然後將ID,名稱和註釋ID投影到別的東西上。這應該適用於訪問者註釋。

+0

感謝您的答案。我不太明白,儘管......在SQL方法中,你的意思是我可以在QueryDSL SQL中調用子查詢嗎?在後一種情況下,你的意思是我應該有一個列表 commentIds(帶有公式)的單獨屬性? –

+0

對於Querydsl SQL,您可以使用子查詢。關於你的第二個問題,不,只是普通的屬性,但懶惰地提取,帶有註釋的屬性,你可以訪問id屬性,但不需要獲取整個對象。 –

+0

謝謝!我以前不知道accessor註釋的效果。我會研究一下:) –

3

最簡單的事情就是查詢帖子並使用fetchJoin進行評論,但我假設對於您的用例來說太慢了。

我認爲你應該簡單地項目所需的屬性的帖子和評論和手動分組結果(如果需要)。例如。

QPost post=...; 
QComment comment=..; 

List<Tuple> rows = q.from(post) 
// Or leftJoin if you want also posts without comments 
.innerJoin(comment).on(comment.postId.eq(post.id)) 
.orderBy(post.id) // Could be used to optimize grouping 
.list(new QTuple(post.id, post.name, comment.id)); 

Map<Long, PostWithComments> results=...; 
for (Tuple row : rows) { 
    PostWithComments res = results.get(row.get(post.id)); 
    if (res == null) { 
    res = new PostWithComments(row.get(post.id), row.get(post.name)); 
    results.put(res.getPostId(), res); 
    } 
    res.addCommentId(row.get(comment.id)); 
} 

注意:這種查詢不能使用限制或偏移。

作爲替代方案,可能會調整映射,以便1)註釋始終是延遲代理,以便(無需初始化實際對象)(有屬性訪問權限)Comment.getId()是可能的; 2)使用批量獲取*在Post.com上優化收集提取。通過這種方式,您可以查詢帖子,然後訪問他們的評論的ID,但幾乎沒有性能影響。在大多數情況下,你甚至不需要那些懶惰的代理,除非你的評論很胖。如果沒有低級別的行處理,那種代碼肯定會更好,你也可以在查詢中使用限制和偏移量。只要留意你的查詢日誌,以確保一切按預期工作。

*)JPA不直接支持批量提取,但Hibernate通過映射和Eclipselink通過查詢提示來支持批量提取。

也許有一天Querydsl將支持這種結果分組後處理的結果分組...

+0

第一個解決方案看起來非常類似於Playframework的Anorm解析器:)您可以獲得感興趣的列,然後解析/提取/合併/變平結果。我真的很希望Querydsl能有這個開箱的... –

+1

聽起來如此:https://bugs.launchpad.net/querydsl/+bug/849735? –