Farzad Afi Logo

FarzadAfi

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

JPA Cascade Types | انواع Cascade در JPA

📖توضیحات درس

🎥 این ویدیو قسمت نود و هشتم از بوت‌کمپ رایگان جاوا است. 📚 در این جلسه از مسیر Java ORM (JPA / Hibernate) سراغ یکی دیگر از مفاهیم بسیار مهم در کار با ارتباط بین Entityها می‌رویم: **Cascade در JPA**. در این ویدیو به صورت کامل بررسی می‌کنیم که Cascade چیست، چرا در طراحی Associationها اهمیت دارد و هر کدام از انواع CascadeType در JPA چه کاربردی دارند. این مفهوم یکی از بخش‌های کلیدی در کار با Hibernate است، چون مشخص می‌کند عملیات مختلفی مثل `persist`، `merge`، `remove` و سایر عملیات‌ها چگونه از یک Entity به Entityهای مرتبط منتقل شوند. در طول ویدیو ابتدا با مفهوم کلی Cascade آشنا می‌شویم و سپس هر یک از انواع مهم آن را به صورت جداگانه بررسی می‌کنیم تا دقیقاً متوجه شوید در چه شرایطی باید از هر کدام استفاده کنید و کجا استفاده نادرست از Cascade می‌تواند باعث رفتارهای ناخواسته در سیستم شود. در این جلسه یاد می‌گیریم: ⚙️ مفهوم Cascade در JPA چیست و چه نقشی در مدیریت Associationها دارد 🧩 بررسی کاربرد `CascadeType.PERSIST` در زمان ذخیره‌سازی Entityها 🔄 بررسی رفتار `CascadeType.MERGE` هنگام به‌روزرسانی موجودیت‌ها 🗑 بررسی `CascadeType.REMOVE` و تاثیر آن در حذف داده‌های مرتبط ✂️ آشنایی با `CascadeType.DETACH` و جدا شدن Entityها از Persistence Context 🔒 بررسی `CascadeType.LOCK` و کاربرد آن در سناریوهای خاص ♻️ بررسی `CascadeType.REFRESH` برای همگام‌سازی مجدد داده‌ها با دیتابیس 📦 بررسی `CascadeType.ALL` و اینکه دقیقاً چه عملیات‌هایی را شامل می‌شود 🧠 در پایان هم یک جمع‌بندی کامل از نکات مهم جلسه خواهیم داشت اگر در حال یادگیری Hibernate یا JPA هستید، درک درست Cascadeها یکی از مهارت‌های مهمی است که به شما کمک می‌کند ارتباط بین Entityها را اصولی‌تر طراحی کنید و از مشکلاتی مثل حذف ناخواسته داده‌ها، ذخیره نشدن آبجکت‌های مرتبط یا رفتارهای غیرمنتظره در Persistence Layer جلوگیری کنید. 📌یوتیوب: youtube.com/@farzadafi 📌آپارت: aparat.com/farzadafi 📌وب سایت: https://farzadafi.ir 📌 گروه پرسش و پاسخ تلگرام: @programmingByFarzadAfi 💬 گروه پرسش و پاسخ بله: @programming_by_farzadafi هر سوالی داشته باشید میتونید داخل این گروه بپرسید تا خودم یا مربی هایی که در گروه حضور دارن کمکتون کنیم :) 🎯 بوت کمپ رایگان جاوا آموزش جاوا پروژه محور
01:03:23🎯رایگان

📄جزوه

مفاهیم کلیدی

  • Cascade

در JPA، Cascade یعنی وقتی روی یک Entity والد عملیاتی انجام می‌دهید، همان عملیات به صورت خودکار روی Entityهای وابسته نیز اعمال شود. این قابلیت برای مدیریت صحیح روابطی مثل OneToMany و ManyToOne بسیار مهم است.

  • وابستگی بین Entityها

برخی Entityها به صورت مفهومی وابسته به Entity دیگری هستند. مثلاً Address بدون Person معمولاً معنای مستقلی در مدل دامنه ندارد. در چنین شرایطی Cascade کمک می‌کند عملیات والد به فرزند نیز منتقل شود.

  • CascadeType

در JPA، انواع مختلفی از CascadeType تعریف شده‌اند که مشخص می‌کنند چه عملیاتی از والد به فرزند propagate شود. انواع استاندارد JPA شامل ALL، PERSIST، MERGE، REMOVE، REFRESH و DETACH هستند.

  • CascadeType.ALL

این گزینه باعث می‌شود تمام عملیات‌های اصلی چرخه حیات Entity از والد به فرزند منتقل شوند. یعنی اگر روی والد persist، merge، remove، refresh یا detach انجام شود، همان عملیات روی فرزند نیز اعمال خواهد شد.
این گزینه زمانی مناسب است که چرخه حیات فرزند کاملاً وابسته به والد باشد.

  • CascadeType.PERSIST

اگر والد با persist() ذخیره شود، فرزند نیز به صورت خودکار ذخیره می‌شود. این حالت برای زمانی کاربرد دارد که یک Entity جدید به همراه فرزندان جدیدش ساخته شده و باید همه با هم وارد دیتابیس شوند.

  • CascadeType.MERGE

اگر یک Entity والد detached باشد و با merge() دوباره به Persistence Context متصل شود، وضعیت فرزندان آن نیز merge می‌شود.
این عملیات معمولاً ابتدا وضعیت موجود را از دیتابیس می‌خواند و سپس تغییرات را روی نمونه managed اعمال می‌کند.

  • CascadeType.REMOVE

اگر والد حذف شود، فرزندهای وابسته نیز حذف می‌شوند. این نوع cascade زمانی مفید است که حذف والد باید منجر به حذف کامل داده‌های وابسته شود.

  • CascadeType.DETACH

اگر والد از Persistence Context خارج شود، فرزندان آن نیز از context خارج می‌شوند. در نتیجه دیگر توسط EntityManager track نخواهند شد.

  • CascadeType.REFRESH

اگر والد با refresh() دوباره از دیتابیس بارگذاری شود، فرزندان آن نیز refresh می‌شوند. این کار برای بازگرداندن تغییرات local و همگام‌سازی مجدد با دیتابیس کاربرد دارد.

  • Persistence Context

محیطی است که EntityManager در آن Entityها را مدیریت می‌کند. وقتی یک Entity داخل این context باشد، تغییراتش track می‌شود. رفتار Cascade مستقیماً با همین context و عملیات چرخه حیات مرتبط است.

  • Parent-Child Relationship

در روابطی مانند @OneToMany و @ManyToOne معمولاً Cascade روی سمت والد تعریف می‌شود تا عملیات والد به collection فرزندان منتقل شود.

مثال:

@OneToMany(mappedBy = "person", cascade = CascadeType.ALL)
private List<Address> addresses;
  • جهت اعمال Cascade

Cascade از سمتی اعمال می‌شود که آن را تعریف کرده‌اید. اگر روی والد تعریف شود، عملیات والد به فرزند propagate می‌شود؛ نه برعکس.

  • Transient to Persistent Transition

یکی از رایج‌ترین کاربردهای Cascade زمانی است که یک والد و فرزند هر دو جدید هستند. با CascadeType.PERSIST فقط کافی است والد را persist کنید تا فرزندها هم persistent شوند.

  • Detached Entity Merge Behavior

در merge()، JPA معمولاً نمونه detached را مستقیماً managed نمی‌کند، بلکه state آن را به یک نمونه managed با همان شناسه منتقل می‌کند. اگر cascade فعال باشد، همین منطق برای فرزندها نیز اجرا می‌شود.


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

  • Cascade در JPA چیست؟

مکانیزمی است که باعث می‌شود عملیات چرخه حیات Entity مانند persist، merge، remove و refresh از والد به Entityهای مرتبط منتقل شود.

  • تفاوت CascadeType.PERSIST و CascadeType.MERGE چیست؟

PERSIST برای ذخیره Entityهای جدید استفاده می‌شود، اما MERGE برای همگام‌سازی وضعیت یک Entity detached با نمونه managed در Persistence Context به کار می‌رود.

  • چه زمانی از CascadeType.ALL استفاده می‌کنیم؟

وقتی چرخه حیات فرزند کاملاً به والد وابسته باشد و بخواهیم تمام عملیات اصلی به صورت خودکار به فرزند نیز اعمال شوند.

  • اگر CascadeType.REMOVE فعال باشد چه اتفاقی می‌افتد؟

با حذف Entity والد، Entityهای فرزند مرتبط نیز حذف می‌شوند.

  • آیا Cascade روی هر دو سمت رابطه اعمال می‌شود؟

خیر، فقط از سمتی اعمال می‌شود که در annotation تعریف شده است.

  • تفاوت CascadeType.REMOVE با حذف دستی فرزندها چیست؟

در REMOVE، حذف فرزندها به صورت خودکار و declarative انجام می‌شود؛ اما در حذف دستی، توسعه‌دهنده باید خودش ترتیب و منطق حذف را مدیریت کند.

  • CascadeType.DETACH چه کاربردی دارد؟

زمانی که بخواهیم والد و فرزندانش هم‌زمان از Persistence Context خارج شوند تا دیگر تغییرات آن‌ها track نشود.

  • refresh() همراه با cascade چه کاری انجام می‌دهد؟

وضعیت والد و فرزندها را از روی دیتابیس دوباره بارگذاری می‌کند و تغییرات local ذخیره‌نشده را از بین می‌برد.

  • آیا Cascade به معنی fetch کردن خودکار است؟

خیر، Cascade مربوط به propagation عملیات چرخه حیات است، در حالی که fetch نحوه بارگذاری داده را مشخص می‌کند.

  • اشتباه رایج در استفاده از CascadeType.ALL چیست؟

استفاده بدون تحلیل مدل دامنه؛ چون ممکن است باعث حذف یا به‌روزرسانی ناخواسته Entityهای وابسته شود.


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

فرض کنید یک Person دارای چند Address است و در مدل دامنه، آدرس‌ها بخشی از چرخه حیات شخص محسوب می‌شوند. در این حالت روی رابطه OneToMany از CascadeType.PERSIST یا CascadeType.ALL استفاده می‌کنیم.

@Entity
public class Person {
    @OneToMany(mappedBy = "person", cascade = CascadeType.ALL)
    private List<Address> addresses;
}

اکنون اگر یک Person جدید همراه با یک Address جدید بسازیم و فقط والد را ذخیره کنیم:

entityManager.persist(person);

JPA به صورت خودکار فرزندها را نیز ذخیره می‌کند.
همین منطق برای حذف نیز برقرار است؛ اگر CascadeType.REMOVE یا ALL فعال باشد، با حذف Person، تمام Addressهای وابسته نیز حذف می‌شوند.

در سناریوی update نیز اگر Person و Address detached باشند و والد را merge() کنیم، تغییرات فرزند هم به صورت خودکار merge می‌شود. این رفتار باعث می‌شود مدیریت graph شیءها ساده‌تر شود، به شرطی که وابستگی دامنه درست طراحی شده باشد.


بیشتر بدانید

  • Cascade با Relationship Design

قبل از انتخاب CascadeType باید مشخص کنید آیا فرزند واقعاً مالک چرخه حیات مستقل است یا نه. اگر مستقل باشد، استفاده از CascadeType.ALL ممکن است خطرناک باشد.

  • Cascade با fetch متفاوت است

Cascade تعیین می‌کند چه عملیاتی propagate شوند، اما FetchType.LAZY و FetchType.EAGER فقط نحوه لود شدن داده را کنترل می‌کنند.

  • انتخاب حداقلی بهتر از انتخاب حداکثری است

در بسیاری از پروژه‌ها بهتر است به جای CascadeType.ALL فقط cascadeهای موردنیاز مثل PERSIST و MERGE را فعال کنید.

  • در روابط حساس روی REMOVE دقت کنید

اگر فرزندها shared باشند یا در بخش‌های دیگر سیستم هم استفاده شوند، CascadeType.REMOVE می‌تواند باعث حذف ناخواسته داده‌ها شود.

  • الگوی رایج در پروژه‌های واقعی

برای aggregateهایی که فرزند بدون والد معنای مستقلی ندارد، ترکیب CascadeType.PERSIST و CascadeType.MERGE بسیار رایج و امن‌تر از استفاده پیش‌فرض از ALL است.