كيف أكتب استعلام JPQL هذا؟
سؤال
قل لدي 5 طاولات ،
tblBlogs tblBlogPosts tblBlogPostComment tblUser tblBlogMember
BlogId BlogPostsId BlogPostCommentId UserId BlogMemberId
BlogTitle BlogId CommentText FirstName UserId
PostTitle BlogPostsId BlogId
BlogMemberId
الآن أريد استرداد فقط تلك المدونات والمنشورات التي علق عليها عضو المدونة بالفعل. باختصار ، كيف أكتب هذا 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 (من say 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 ، حاولت كتابة استعلام 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
حسنًا ، هذا هو الجواب النهائي. استغرق الأمر ساعة واحدة لتأطير هذا السطر الواحد. حصلت على العديد من الأخطاء الغريبة خلال هذه الساعة ، لكن مفاهيمي الآن واضحة بما يكفي:
@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")
نصائح أخرى
في JPQL ، يمكننا فقط كتابة استفسارات بسيطة (...)
هذا ليس صحيحًا و JPQL يدعم [ LEFT [OUTER] | INNER ] JOIN
. للوصول الداخلي ، راجع القسم 4.4.5.1 inner inner (تنضم العلاقة) من المواصفات:
4.4.5.1 inner inner (تنضم العلاقة)
بناء الجملة لعملية الانضمام الداخلية
[ INNER ] JOIN join_association_path_expression [AS] identification_variable
على سبيل المثال ، ينضم الاستعلام أدناه إلى العلاقة بين العملاء والأوامر. هذا النوع من الصلة يعادل عادةً الانضمام إلى علاقة مفتاح خارجي في قاعدة البيانات.
SELECT c FROM Customer c JOIN c.orders o WHERE c.status = 1
قد يتم استخدام الكلمة الرئيسية الداخلية اختياريًا:
SELECT c FROM Customer c INNER JOIN c.orders o WHERE c.status = 1
تحتاج فقط إلى التفكير في الارتباط بين الكيانات.