Farzad Afi Logo

FarzadAfi

آموزش تخصصی برنامه نویسی

JPA Query Types | انواع کوئری در JPA

📖توضیحات درس

🎥 این ویدیو قسمت نود و نهم از بوت‌کمپ رایگان جاوا است. 📚 در این جلسه از مسیر Java ORM (JPA / Hibernate) به سراغ یکی از قابلیت‌های حیاتی برای تعامل با دیتابیس می‌رویم: **انواع Query در JPA**. در این ویدیو، ابزارهای مختلفی که JPA برای اجرای کوئری‌ها در اختیار ما قرار می‌دهد را بررسی می‌کنیم. از کوئری‌های ساده گرفته تا روش‌های پیشرفته‌تر مانند Criteria API و Native Query. درک اینکه چه زمانی از کدام روش برای نوشتن کوئری استفاده کنید، دانش لازم برای بهینه‌سازی و نوشتن کدهای تمیز در لایه‌ی Persistence است. در طول ویدیو، هر یک از این روش‌ها را معرفی کرده و با نگاهی به مزایا و معایب هر کدام، بررسی می‌کنیم که کدام‌یک در چه سناریویی بهترین خروجی را به ما می‌دهد. در این جلسه یاد می‌گیریم: ⚙️ **Query:** آشنایی با پایه و اساس اجرای کوئری‌ها در JPA 🎯 **TypedQuery:** نحوه استفاده از Type-safe Queryها برای جلوگیری از خطاهای زمان اجرا 🔖 **NamedQuery:** سازماندهی کوئری‌ها و استفاده از آن‌ها به صورت نام‌گذاری شده ⚔️ **NativeQuery:** زمانی که نیاز داریم مستقیماً با SQL خام با دیتابیس صحبت کنیم 📊 **Criteria API:** روشی کاملاً شیء‌گرا و داینامیک برای ساخت کوئری‌های پیچیده ⚖️ **Pros and Cons:** بررسی نقاط قوت و ضعف هر روش برای تصمیم‌گیری آگاهانه 🧠 در پایان نیز یک جمع‌بندی کامل از نکات مهم این جلسه خواهیم داشت اگر در حال یادگیری Hibernate یا JPA هستید، تسلط بر نحوه کوئری‌نویسی و انتخاب روش درست (Query vs NativeQuery vs Criteria)، مهارت شما در حل مسائل پیچیده دیتابیسی را به سطح بالاتری می‌برد. 📌یوتیوب: youtube.com/@farzadafi 📌آپارت: aparat.com/farzadafi 📌وب سایت: https://farzadafi.ir 📌 گروه پرسش و پاسخ تلگرام: @programmingByFarzadAfi 💬 گروه پرسش و پاسخ بله: @programming_by_farzadafi وب سایت: https://farzadafi.ir هر سوالی داشته باشید می‌توانید در گروه بپرسید تا من یا مربی‌های گروه کمکتان کنیم 💬 🎯 بوت‌کمپ رایگان جاوا – آموزش کاملاً پروژه‌محور برای یادگیری عمیق جاوا و ورود به بازار کار.
00:40:03🎯رایگان

📄جزوه

مفاهیم کلیدی

  • JPA Query

در JPA برای خواندن یا تغییر داده‌ها از مکانیزمی به نام Query استفاده می‌شود. این Queryها معمولاً با استفاده از EntityManager اجرا می‌شوند و داده‌های دیتابیس را به Entityهای جاوا map می‌کنند. در JPA سه نوع اصلی Query وجود دارد: JPQL Query، Native Query و Criteria API Query.


  • JPQL (Java Persistence Query Language)

یک زبان Query سطح بالا مشابه SQL است اما به جای table و column با Entity و fieldهای آن کار می‌کند.
JPA این Queryها را به SQL مناسب دیتابیس تبدیل می‌کند، بنابراین مستقل از نوع دیتابیس هستند.

مثال:

Query query = entityManager.createQuery(
    "SELECT u FROM UserEntity u WHERE u.id = :id"
);
query.setParameter("id", id);

  • TypedQuery

نوعی Query در JPA است که نوع خروجی آن مشخص شده است. این کار باعث افزایش type safety می‌شود و نیاز به casting را حذف می‌کند.

مثال:

TypedQuery<UserEntity> query =
    entityManager.createQuery(
        "SELECT u FROM UserEntity u WHERE u.id = :id",
        UserEntity.class
    );

UserEntity user = query.getSingleResult();

مزیت اصلی آن جلوگیری از خطاهای runtime ناشی از cast اشتباه است.


  • NamedQuery

یک Query از پیش تعریف شده است که معمولاً روی کلاس Entity یا در فایل‌های پیکربندی تعریف می‌شود.
هدف آن متمرکز کردن Queryها و افزایش maintainability است.

مثال تعریف:

@Entity
@NamedQuery(
    name = "UserEntity.findByUserId",
    query = "SELECT u FROM UserEntity u WHERE u.id = :userId"
)
public class UserEntity {
}

استفاده:

Query query = entityManager.createNamedQuery("UserEntity.findByUserId");
query.setParameter("userId", id);

  • Native Query

یک Query که مستقیماً با SQL دیتابیس نوشته می‌شود. در این حالت JPA هیچ abstraction خاصی روی SQL اعمال نمی‌کند.

مثال:

Query query = entityManager.createNativeQuery(
    "SELECT * FROM users WHERE id = :id",
    UserEntity.class
);

مزیت اصلی آن استفاده از قابلیت‌های خاص دیتابیس است.


  • Criteria API

یک روش برنامه‌نویسی برای ساخت Query به صورت programmatic و type-safe است. به جای نوشتن Query به صورت string، از objectها و متدها استفاده می‌شود.

مثال:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<UserEntity> cq = cb.createQuery(UserEntity.class);
Root<UserEntity> root = cq.from(UserEntity.class);

cq.select(root)
  .where(cb.equal(root.get("id"), id));

UserEntity result =
    entityManager.createQuery(cq).getSingleResult();

این روش مخصوصاً برای Queryهای dynamic بسیار مفید است.


  • Database Portability

یکی از مزیت‌های اصلی JPQL این است که Queryها مستقل از دیتابیس هستند. اما در NativeQuery ممکن است از قابلیت‌های خاص دیتابیس استفاده شود که portability را کاهش می‌دهد.


موارد مصاحبه ای

  • What are the main types of queries in JPA?

سه نوع اصلی وجود دارد:
JPQL Query، Native Query و Criteria API Query.


  • What is the difference between JPQL and SQL?

در JPQL به جای table و column از Entity و fieldهای آن استفاده می‌شود. JPA این Queryها را به SQL مناسب دیتابیس تبدیل می‌کند.


  • Why is TypedQuery preferred over Query?

چون TypedQuery نوع خروجی را مشخص می‌کند و از نیاز به casting جلوگیری کرده و type safety را افزایش می‌دهد.


  • What is NamedQuery in JPA?

یک Query از پیش تعریف شده است که معمولاً در کلاس Entity یا فایل configuration تعریف می‌شود و با نام مشخصی قابل فراخوانی است.


  • When should we use NativeQuery?

زمانی که به قابلیت‌های خاص دیتابیس نیاز داریم یا می‌خواهیم SQL بهینه‌تری نسبت به SQL تولیدی JPA بنویسیم.


  • What is the advantage of Criteria API?

امکان ساخت Queryهای dynamic و type-safe به صورت programmatic را فراهم می‌کند.


  • Why are NamedQueries more performant?

چون هنگام بارگذاری Persistence Unit کامپایل و validate می‌شوند و در زمان اجرا نیاز به parse مجدد ندارند.


  • What is the drawback of NativeQuery?

از بین رفتن portability بین دیتابیس‌های مختلف به دلیل وابستگی به SQL مخصوص vendor.


سناریو کاربردی

فرض کنید در یک سیستم، Entity زیر وجود دارد:

@Entity
@Table(name = "users")
public class UserEntity {
    @Id
    private Long id;
    private String name;
}

سه روش برای دریافت کاربر با id مشخص وجود دارد.

روش اول: JPQL Query

Query query = entityManager.createQuery(
    "SELECT u FROM UserEntity u WHERE u.id = :id"
);
query.setParameter("id", id);
UserEntity user = (UserEntity) query.getSingleResult();

روش دوم: TypedQuery

TypedQuery<UserEntity> query =
    entityManager.createQuery(
        "SELECT u FROM UserEntity u WHERE u.id = :id",
        UserEntity.class
    );

UserEntity user = query.getSingleResult();

روش سوم: NativeQuery

Query query = entityManager.createNativeQuery(
    "SELECT * FROM users WHERE id = :id",
    UserEntity.class
);

روش چهارم: Criteria API

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<UserEntity> cq = cb.createQuery(UserEntity.class);
Root<UserEntity> root = cq.from(UserEntity.class);

cq.select(root)
  .where(cb.equal(root.get("id"), id));

UserEntity user = entityManager.createQuery(cq).getSingleResult();

در پروژه‌های واقعی معمولاً از JPQL یا TypedQuery برای Queryهای ساده و از Criteria API برای Queryهای dynamic استفاده می‌شود.


بیشتر بدانید

  • استفاده از setParameter

به جای قرار دادن مستقیم مقدار در Query از setParameter استفاده کنید تا از مشکلات امنیتی مانند SQL Injection جلوگیری شود.


  • مزیت JPQL نسبت به NativeQuery

JPQL مستقل از دیتابیس است و JPA خودش Query مناسب دیتابیس را تولید می‌کند.


  • استفاده از NamedQuery در پروژه‌های بزرگ

در پروژه‌هایی که تعداد Query زیاد است، تعریف Queryها به صورت NamedQuery باعث خوانایی و maintainability بهتر می‌شود.


  • Criteria API برای Queryهای Dynamic

اگر شرایط Query در runtime تغییر می‌کند (مثلاً فیلترهای جستجو)، استفاده از Criteria API بسیار مناسب‌تر از ساخت Query string است.


  • مشکل نگهداری Queryهای پراکنده

اگر Queryها در متدهای مختلف نوشته شوند، نگهداری پروژه سخت می‌شود. استفاده از NamedQuery یا لایه Repository می‌تواند این مشکل را کاهش دهد.