جلسه شماره 140رایگان

Spring Data JPA in Action | اسپرینگ دیتا جی پی ای در عمل

00:18:15

توضیحات جلسه

🎥 این ویدیو قسمت صد و بیست و یکم از بوت‌کمپ رایگان جاوا و بیستمین جلسه از پلی‌لیست تخصصی آموزش اسپرینگ است. 📚 در این جلسه به سراغ Spring Data JPA می‌رویم تا ببینیم چطور می‌توانیم لایه دسترسی به داده را به شکل مدرن و استاندارد در پروژه پیاده‌سازی کنیم. در این ویدیو یاد می‌گیریم که چطور Spring Data JPA را به پروژه اضافه کنیم، مدل‌های دامنه (Domain Models) را با انوتیشن‌های مربوطه مجهز کنیم، ریپازیتوری‌های JPA را تعریف کنیم و در نهایت برنامه Taco Cloud را با تغییرات جدید تست کنیم تا کارکرد درست ارتباط با دیتابیس را بررسی کنیم. در این جلسه یاد می‌گیریم: ⚙️ آشنایی با مفهوم و کاربرد Spring Data JPA در اسپرینگ بوت 📦 نحوه اضافه کردن وابستگی Spring Data JPA به پروژه 🏷️ انوتیشن‌گذاری کلاس‌های دامنه و آماده‌سازی Entityها 🛠️ تعریف و پیاده‌سازی JPA Repository برای مدیریت داده‌ها 🧪 تست کامل برنامه Taco Cloud با ساختار جدید 🧠 جمع‌بندی نکات مهم و بررسی مزایای Spring Data JPA در مقایسه با روش‌های سنتی اگر در حال یادگیری اسپرینگ و کار با دیتابیس در جاوا هستید، تسلط بر Spring Data JPA یکی از مهارت‌های اصلی و کلیدی برای توسعه سریع‌تر و تمیزتر برنامه‌های سازمانی است. 📌 یوتیوب: https://youtube.com/@farzadafi 📌 آپارت: https://aparat.com/farzadafi 📌 وب‌سایت: https://farzadafi.ir 📌 گروه پرسش و پاسخ تلگرام: @programmingByFarzadAfi 💬 گروه پرسش و پاسخ بله: @programming_by_farzadafi وب سایت: https://farzadafi.ir هر سوالی داشته باشید می‌توانید در گروه بپرسید تا من یا مربی‌های گروه کمکتان کنیم 💬 🎯 بوت‌کمپ رایگان جاوا – آموزش کاملاً پروژه‌محور برای یادگیری عمیق جاوا و ورود به بازار کار.

جزوه و مستندات

مفاهیم کلیدی

  • Spring Data JPA

بخشی از اکوسیستم بزرگ Spring Data که با ایجاد یک لایه انتزاعی بر روی استانداردهای JPA، عملیات ذخیره‌سازی، خواندن و مدیریت موجودیت‌ها در دیتابیس‌های رابطه‌ای را بدون نیاز به پیاده‌سازی دستی ریپازیتوری‌ها میسر می‌سازد.

  • JPA Starter Dependency

وابستگی آغازگر در اسپرینگ بوت (spring-boot-starter-data-jpa) که علاوه بر ماژول Spring Data JPA، پیاده‌سازی پیش‌فرض JPA یعنی Hibernate را به همراه تمام پیش‌نیازهای ترنزتیو به ساختار پروژه اضافه می‌کند.

  • @Entity

انوتیشن بنیادین در استاندارد JPA که مشخص می‌کند کلاس نشانه‌گذاری‌شده یک موجودیت پایگاه داده است و چرخه حیات و نگاشت ردیف‌های آن توسط ارائه‌دهنده پایداری داده مدیریت می‌شود.

  • @GeneratedValue

انوتیشنی برای مشخص کردن استراتژی تولید کلید اصلی خودکار توسط پایگاه داده؛ مانند GenerationType.AUTO که نوع تخصیص شناسه را به رفتار ارائه‌دهنده پایداری داده و پایگاه داده واگذار می‌کند.

  • Entity Relationships

انوتیشن‌های نگاشت رابطه در مدل شیء-رابطه‌ای؛ شامل @ManyToMany برای نمایش وابستگی چندبه‌چند (مانند رابطه بین Taco و Ingredient) و @OneToMany برای ارتباط یک‌به‌چند (مانند رابطه بین TacoOrder و Taco).

  • Cascade Operations

مکانیزمی در نگاشت روابط که اعمال یک عملیات روی موجودیت والد را به موجودیت‌های وابسته سرایت می‌دهد؛ به عنوان نمونه مقدار CascadeType.ALL در حذف سفارش سبب حذف خودکار تمام تاکوهای درون آن سفارش می‌شود.

  • JPA Constructor Contract

قاعده استاندارد در JPA مبنی بر الزام موجودیت‌ها به داشتن یک سازنده بدون آرگومان (No-args Constructor) جهت نمونه‌سازی پویا در لایه بازتابی؛ توسعه‌دهندگان معمولاً با استفاده از انوتیشن Lombok نظیر @NoArgsConstructor(access = AccessLevel.PRIVATE, force = true) این سازنده را بدون باز گذاشتن دسترسی عمومی ایجاد می‌کنند.

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

  • تفاوت پکیج انوتیشن @Id در Spring Data JDBC و Spring Data JPA چیست؟

در Spring Data JPA انوتیشن @Id از پکیج استانداردهای جاوا (javax.persistence یا jakarta.persistence) تامین می‌شود؛ در حالی که در Spring Data JDBC از پکیج اختصاصی org.springframework.data.annotation استفاده می‌گردد و جابه‌جایی نادرست آن‌ها باعث خطای عدم شناسایی شناسه می‌شود.

  • چرا اینترفیس Persistable در Spring Data JPA بر خلاف Spring Data JDBC مورد نیاز نیست؟

در Spring Data JDBC تعیین وضعیت شیء (جدید بودن یا به‌روزرسانی بودن) در موارد فاقد شناسه خودکار نیازمند پیاده‌سازی متد isNew() از طریق Persistable بود؛ اما در JPA کانتکست پایداری و متدهای فریم‌ورک به طور خودکار با ردیابی کانتکست پایداری موجودیت، دستور مناسب (persist یا merge) را صادر می‌کنند.

  • چگونه می‌توان پیاده‌ساز پیش‌فرض JPA (یعنی Hibernate) را با پیاده‌ساز دیگری مانند EclipseLink تعویض کرد؟

باید ماژول hibernate-core را درون بلاک وابستگی spring-boot-starter-data-jpa از طریق تگ <exclusions> مستثنی کرد و سپس وابستگی مربوط به کتابخانه مورد نظر (نظیر org.eclipse.persistence.jpa) را به فایل pom.xml اضافه نمود.

  • چرا هنگام استفاده همزمان از @Data و @NoArgsConstructor در کلاس‌های JPA، انوتیشن @RequiredArgsConstructor به شکل صریح ضروری می‌شود؟

انوتیشن @Data سازنده فیلدهای اجباری (final) را فقط زمانی به شکل پیش‌فرض تولید می‌کند که هیچ سازنده دیگری تعریف نشده باشد؛ به محض تعریف @NoArgsConstructor، سازنده فیلدهای اجباری حذف می‌شود و باید با انوتیشن @RequiredArgsConstructor به صورت دستی بازگردانده شود.

  • نقش اینترفیس CrudRepository در همگرایی پروژه‌های مختلف Spring Data چیست؟

اینترفیس CrudRepository به عنوان یک قرارداد یکنواخت انتزاعی در کلیه زیرپروژه‌های Spring Data (شامل JDBC، JPA، MongoDB و ...) عمل می‌کند؛ به همین دلیل تعریف کدهای ریپازیتوری در سطح اینترفیس هنگام مهاجرت از Spring Data JDBC به Spring Data JPA بدون تغییر باقی می‌ماند.

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

  • مدل‌سازی موجودیت‌های دامنه با نگاشت JPA و برقراری روابط آبشاری

در این سناریو کلاس‌های سفارش و آیتم‌های تاکو از ساختار قبلی JDBC به مدل استاندارد JPA تبدیل شده و رابطه یک‌به‌چند همراه با انتشار آبشاری پیکربندی می‌شود:

@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE, force = true)
public class Ingredient {

    @Id
    private String id;
    private String name;
    private Type type;

    public enum Type {
        WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE
    }
}
@Data
@Entity
public class Taco {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    private Date createdAt = new Date();

    @ManyToMany
    private List<Ingredient> ingredients = new ArrayList<>();
}
@Data
@Entity
@Table(name = "Taco_Order")
public class TacoOrder implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private Date placedAt = new Date();

    private String deliveryName;
    private String deliveryStreet;
    private String deliveryCity;
    private String deliveryState;
    private String deliveryZip;
    private String ccNumber;
    private String ccExpiration;
    private String ccCVV;

    @OneToMany(cascade = CascadeType.ALL)
    private List<Taco> tacos = new ArrayList<>();

    public void addTaco(Taco taco) {
        this.tacos.add(taco);
    }
}

و در لایه دسترسی به داده، اینترفیس‌ها مستقیماً بر مبنای CrudRepository سازمان‌دهی می‌شوند:

public interface OrderRepository extends CrudRepository<TacoOrder, Long> {
}

بیشتر بدانید

  • ویژگی force در NoArgsConstructor برای فیلدهای final

هنگامی که در موجودیت‌ها فیلدهای نهایی (final) تعریف شده باشند، اضافه کردن آرگومان force = true در انوتیشن @NoArgsConstructor الزامی است تا کامپایلر لومبوک این فیلدها را در سازنده پیش‌فرض با مقادیر اولیه خام (مانند null یا صفر یا false) مقداردهی کند و خطای کامپایل جاوا رفع شود.

  • انتخاب سطح دسترسی سازنده برای JPA

تنظیم access = AccessLevel.PRIVATE در انوتیشن سازنده بدون آرگومان باعث می‌شود این متد از دید سایر لایه‌های کد تجاری پروژه مخفی بماند و فقط از طریق سازوکارهای درونی Reflection فریم‌ورک JPA در زمان اجرای برنامه فراخوانی گردد.