我该如何编写这个JPQL查询?

时间:2010-05-16 14:00:28

标签: java orm jpa jpql

说我有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查询返回什么类型的对象?因为我只从所有表中选择几个字段。我应该在哪个类中将结果转换为?

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

更新:根据pascal的回答,我尝试为上述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

以上查询无效。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:13)

  

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

这不是真的,JPQL确实支持 [ LEFT [OUTER] | INNER ] JOIN 。对于内部连接,请参阅规范的 4.4.5.1内部连接(关系连接)部分:

  

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

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

答案 1 :(得分:9)

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

@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")