7

假设我有 5 张桌子,

tblBlogs     tblBlogPosts     tblBlogPostComment    tblUser    tblBlogMember
BlogId        BlogPostsId       BlogPostCommentId   UserId      BlogMemberId
BlogTitle     BlogId            CommentText         FirstName   UserId
              PostTitle         BlogPostsId                     BlogId
                                 BlogMemberId

现在我只想检索那些 blogMember 实际评论过的博客和帖子。简而言之,我该如何编写这个简单的旧 SQL?

SELECT b.BlogTitle, bp.PostTitle, bpc.CommentText FROM tblBlogs b 
INNER JOIN tblBlogPosts bp on b.BlogId = bp.BlogId 
INNER JOIN tblBlogPostComment bpc on bp.BlogPostsId = bpc.BlogPostsId 
INNER JOIN  tblBlogMember bm ON bpc.BlogMemberId = bm.BlogMemberId 
WHERE bm.UserId = 1;

如您所见,一切都是内连接,因此只会检索用户对某个博客的某些帖子发表评论的那一行。所以,假设他/她加入了 3 个 id 为 1,2,3 的博客(用户加入的博客在 tblBlogMembers 中),但用户只在博客 2 中发表了评论(比如 BlogPostId = 1)。所以该行将被检索,而 1,3 不会因为它是内部联接。如何在JPQL中编写这种查询?

在 JPQL 中,我们只能编写简单的查询,例如:

Select bm.blogId from tblBlogMember Where bm.UserId = objUser;

其中 objUser 使用以下方式提供:

em.find(User.class,1);

因此,一旦我们得到用户加入的所有博客(这里 blogId 代表一个博客对象),我们就可以循环并做所有花哨的事情。但我不想陷入这种循环业务并在我的 Java 代码中编写所有这些东西。相反,我想把它留给数据库引擎去做。那么,如何将上面的纯 SQL 写入 JPQL 呢?JPQL 查询将返回什么类型的对象?因为我只从所有表中选择几个字段。我应该将结果类型转换到哪个类?

我想我正确地发布了我的要求,如果我不清楚,请告诉我。

更新:根据帕斯卡的回答,我尝试为上述 SQL 查询编写 JPQL 查询。我面临一个小问题。此查询有效,但不完整:

SELECT bm.blogId FROM BlogMembers bm 
    INNER JOIN bm.blogId b 
    INNER JOIN b.blogPostsList bp 
    INNER JOIN bp.blogPostCommentList bpc 
    WHERE bm.userId = :userId

我想将其修改为:

SELECT bm.blogId FROM BlogMembers bm 
    INNER JOIN bm.blogId b 
    INNER JOIN b.blogPostsList bp 
    INNER JOIN bp.blogPostCommentList bpc 
    WHERE bpc.blogMembersId = bm.blogMembersId AND bm.userId = :userId

上面的查询不起作用。我怎么解决这个问题?

4

2 回答 2

17

在 JPQL 中,我们只能编写简单的查询 (...)

这不是真的,JPQL 确实支持[ LEFT [OUTER] | INNER ] JOIN. 对于Inner Joins,请参考规范的4.4.5.1 Inner Joins(关系连接)小节:

4.4.5.1 内连接(关系连接)

内连接操作的语法是

[ INNER ] JOIN join_association_path_expression [AS] identification_variable

例如,下面的查询连接了客户和订单之间的关系。这种类型的连接通常等同于通过数据库中的外键关系进行连接。

SELECT c FROM Customer c JOIN c.orders o WHERE c.status = 1

可以选择使用关键字 INNER:

SELECT c FROM Customer c INNER JOIN c.orders o WHERE c.status = 1

您只需要考虑实体之间的关联。

于 2010-05-16T14:33:41.130 回答
10

好的,这是最终答案。构图这一行花了一个小时。我在这个小时内遇到了许多奇怪的错误,但现在我的概念已经足够清晰了:

@NamedQuery(name = "BlogMembers.findBlogsOnWhichCommentsAreMade", 
    query = "SELECT bm.blogId FROM BlogMembers bm INNER JOIN bm.blogId b 
    INNER JOIN b.blogPostsList bp INNER JOIN bp.blogPostCommentList bpc 
    INNER JOIN bpc.blogMembersId bmt WHERE bm.userId = :userId")
于 2010-05-16T16:17:27.467 回答