Spring Data Custom Queries | کوئری سفارشی در اسپرینگ دیتا
توضیحات جلسه
جزوه و مستندات
مفاهیم کلیدی
- Repository Method Query Derivation
مکانیزم قدرتمند در Spring Data که به فریمورک اجازه میدهد با تحلیل و تجزیه نام متدهای تعریفشده در اینترفیسهای ریپازیتوری، کوئریهای مورد نظر پایگاه داده را به صورت خودکار استخراج و اجرا کند.
- Query DSL
یک زبان اختصاصی کوچک در سطح امضاهای متد ریپازیتوری که به توسعهدهنده اجازه میدهد جزئیات پایداری و جستجوی دادهها را با استفاده از کلمات کلیدی مشخص بیان کند.
- Query Method Structure
ساختار استاندارد نامگذاری متدهای کوئری که از چهار بخش تشکیل شده است: فعل (Verb)، موضوع اختیاری (Subject)، جداکننده (By) و گزاره شرطی (Predicate).
@QueryAnnotation
انوتیشن کاربردی برای تعریف صریح کوئریهای سفارشی روی متدهای ریپازیتوری؛ زمانی که نامگذاری متد بسیار طولانی یا پیچیده شود، از این انوتیشن برای نگارش مستقیم کوئری استفاده میشود.
- Query Keywords and Operators
مجموعهای از کلمات کلیدی و عملگرهای پشتیبانیشده در اسپرینگ دیتا (مانند Between، LessThan، Like، IsNull و IgnoreCase) که شرایط پیشرفتهای را برای فیلتر و جستجوی دادهها فراهم میکنند.
موارد مصاحبه ای
- Spring Data چگونه کوئریهای پایگاه داده را از روی نام متدهای ریپازیتوری تولید میکند؟
فریمورک نام متد را هنگام بالا آمدن برنامه تجزیه میکند؛ ابتدا فعل (مانند find یا read) را تشخیص میدهد، کلمه By را به عنوان مرز شروع شرط در نظر میگیرد و بخش پایانی را به عنوان گزاره (Predicate) برای تطبیق با فیلدها و ویژگیهای موجودیت مورد نظر مپ میکند.
- تفاوت اصلی استفاده از
@Queryدر Spring Data JPA و Spring Data JDBC چیست؟
در Spring Data JPA کوئریهای درون انوتیشن @Query بر مبنای زبان پرسوجوی جیپیای (JPQL) نوشته میشوند، در حالی که در Spring Data JDBC به دلیل نبود فرادادههای نگاشت پیشرفته، کوئریهای داخل @Query باید حتماً به صورت کدهای استاندارد SQL خالص نوشته شوند.
- چگونه میتوان جستجوی مستقل از بزرگ و کوچک بودن حروف (
Case-Insensitive) را در متدهای ریپازیتوری اعمال کرد؟
با افزودن کلمات کلیدی IgnoreCase یا IgnoresCase به انتهای بخش فیلد در نام متد، یا با استفاده از عبارتهای کلیتر مانند AllIgnoringCase در نامگذاری متد برای تمام مقادیر رشتهای.
- نقش بخش موضوع (
Subject) در امضای متدهای ریپازیتوری چیست و آیا وجود آن الزامی است؟
بخش موضوع (مانند Orders در readOrdersBy...) اختیاری است و اسپرینگ دیتا بیشتر کلمات آن را نادیده میگیرد؛ زیرا نوع موجودیت پایگاه داده از طریق پارامترهای اینترفیس CrudRepository از پیش تعیین شده است.
- در چه شرایطی نامگذاری متد بر اساس قرارداد کفایت نمیکند و باید از
@Queryاستفاده کرد؟
هنگامی که پیچیدگی شرطها، پیوستن جدولها (Joins) یا شرایط منطقی به قدری زیاد شود که طول نام متد غیرقابل خواندن و نامعتبر گردد، استفاده از @Query گزینه مناسبتری خواهد بود.
سناریو کاربردی
- کوئریهای سفارشی بر اساس قرارداد نامگذاری و انوتیشن
@Query
در این سناریو، برای دریافت سفارشهای تحویل دادهشده به یک کد پستی خاص یا بازه زمانی مشخص، روشهای متفاوتی در OrderRepository پیادهسازی میشود:
public interface OrderRepository extends CrudRepository<TacoOrder, Long> {
List<TacoOrder> findByDeliveryZip(String deliveryZip);
List<TacoOrder> readOrdersByDeliveryZipAndPlacedAtBetween(
String deliveryZip, Date startDate, Date endDate);
List<TacoOrder> findByDeliveryCityOrderByDeliveryTo(String city);
@Query("SELECT o FROM TacoOrder o WHERE o.deliveryCity = 'Seattle'")
List<TacoOrder> readOrdersDeliveredInSeattle();
}
مراحل کار:
۱. استفاده از متد ساده findByDeliveryZip برای فیلتر مستقیم بر اساس مقدار کد پستی.
۲. استفاده از عملگر Between در متد readOrdersByDeliveryZipAndPlacedAtBetween جهت محدود کردن جستجو در بازه زمانی مشخص.
۳. مرتبسازی نتایج با استفاده از کلیدواژه OrderBy در انتهای نام متد.
۴. بهکارگیری انوتیشن @Query برای اجرای کوئریهای سفارشی و پیچیدهای که ساختار نامگذاری از عهده آنها برنمیآید.
بیشتر بدانید
- افعال مجاز برای بازیابی دادهها
اسپرینگ دیتا افعالی نظیر find، read و get را به عنوان مترادفهای کاملاً یکسان برای دریافت موجودیتها میشناسد و میتوانید به دلخواه از هرکدام استفاده کنید.
- شمارش موجودیتها با فعل count
اگر به جای دریافت لیست موجودیتها، فقط به تعداد رکوردهای منطبق با شرط نیاز داشته باشید، میتوانید به جای find از فعل count در ابتدای نام متد استفاده کنید تا خروجی متد از نوع عدد صحیح باشد.
