Как мне написать этот JPQL-запрос? - PullRequest
6 голосов
/ 16 мая 2010

Скажите, у меня есть 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 блогам с идентификаторами 1,2,3 (блоги, к которым присоединился пользователь, находятся в tblBlogMembers), но пользователь прокомментировал только блог 2 (скажем, BlogPostId = 1). Таким образом, эта строка будет извлечена, а 1,3 - нет, поскольку это Inner Join. Как мне написать запрос такого типа в JPQL ?

В JPQL мы можем писать только простые запросы, например:

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

Где objUser поставляется с использованием:

em.find(User.class,1);

Таким образом, как только мы получим все блоги (здесь blogId представляет объект блога), к которым присоединился пользователь, мы можем пройтись по кругу и делать все модные вещи. Но я не хочу впадать в этот зацикленный бизнес и писать все это в своем коде Java. Вместо этого я хочу оставить это для движка базы данных. Итак, как мне написать приведенный выше простой SQL в JPQL? И какой тип объекта будет возвращать запрос JPQL? Потому что я выбираю только несколько полей из всей таблицы. В каком классе я должен типизировать результат?

Мне кажется, я правильно разместил свое требование, если я не совсем уверен, пожалуйста, дайте мне знать.

ОБНОВЛЕНИЕ: Согласно ответу Паскаля, я пытался написать JPQL-запрос для вышеуказанного SQL-запроса. Я столкнулся с небольшой проблемой. Этот запрос работает, но не завершен:

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 ]

13 голосов
/ 16 мая 2010

В 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

Вам просто нужно подумать об ассоциации между сущностями.

9 голосов
/ 16 мая 2010

Хорошо, это окончательный ответ. Потребовался один час, чтобы создать эту одну строку. В этот час я получил много странных ошибок, но теперь мои концепции достаточно ясны:

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