Relation Mapping در Hibernate جاوا
از سری مقالات آموزش Java Enterprise, مبحث Relation Mapping را بر میگزینیم.
در مقالات قبل, به مفاهیم مورد نیاز برای Hibernate پرداختیم و همچنین بررسی کردیم که چگونه میتوان یک Object را در یک Entity قرار داد و ذخیره کرد. شیوه ذخیره سازی این Object ها در حالتی که Value Object و یا Collection باشند, بررسی شد. در این مقاله میخواهیم قرار گرفتن یک Entity در Entity دیگر را بررسی کنیم. این نوع ذخیره سازی, تا حدودی به روش های قبل شبیه است.
Mapping ها در ارتباطات پایگاه دادهای بسیار رایج است. معمولا داده های ما در پایگاه داده به گونهای ذخیره سازی میشوند که جداول نگهدارنده اطلاعات, با یکدیگر ارتباط دارند. انواع Relation ها در پایگاه داده به این صورت است:
- One to One : در این نوع Relation, هر سطر از جدول فقط به یک سطر از جدول دیگر متصل است. به این معنا که هیچ دو سطری وجود ندارند که به یک سطر از جدول دیگر مرتبط باشند. در یک one to one relation میان جدول الف و ب, هر سطر از جدول الف تنها به یک سطر جدول ب متصل است. برای مثال جدول مشخصات فردی و جدول نشانی ها را در نظر بگیرید. هر نشانی تنها به یک شخص اختصاص دارد و هیچ دو فردی وجود ندارند که نشانی مشترک داشته باشند. این نوع ارتباط One to One است
- One to Many : در این نوع Relation, هر سطر از جدول میتواند به چندین سطر از جدول دیگر مرتبط باشد. در واقع در یک one to many relation, هر سطر جدول الف میتواند به چندین سطر از جدول ب مرتبط باشد. برای مثال, یک جدول را برای نگهداری اطلاعات هر بخش از یک سازمان ایجاد میکنیم. واضح است که هر بخش چندین کارمند دارد. بنابراین یک سطر از جدول بخش های سازمان, میتواند به چندین کارمند مرتبط باشد. مزیت استفاده از این روش, در داده هایی که نرخ تکرار آنها زیاد است, آشکار میشود. در مثالی که ذکر شد, اگر بخواهیم تمام مشخصات هر بخش را برای هر کارمند در جدول اطلاعات کارمندی ذخیره سازی کنیم, یک حجم زیادی از اطلاعات را در پایگاه داده تکرار کردهایم. اما با استفاده از این روش میتوانیم داده ها را بهینه تر نگهداری کنیم.
- Many to Many : در این روش هر تعداد از سطر های جدول الف میتواند به هرچند سطر جدول ب مرتبط باشد. تعداد این ارتباطات صفر, یک و یا بیشتر میتواند باشد. در چنین روشی جدول ثالثی باید حضور داشته باشد تا این ارتباط را پوشش دهد. برای مثال فرض کنید در یک سیستم فروشگاهی, یک کاربر چندین قلم کالا را خریداری کرده است. کالا در جدول مخصوص به کالا ثبت شده است و یک شناسه یکتا دارد. اطلاعات هر کاربر نیز در جدول مشتریان فروشگاه ثبت شده است. در روز جاری, مشتری شماره ۱, کالا الف را خریداری میکند. بنابراین در جدول فروش, شناسه مشتری و شناسه کالا ثبت می شود. مشتری شماره ۲ نیز در همین روز کالای شماره ب را خریداری میکند. چند روز بعد مشتری شماره ۱ کالای ب و مشتری شماره ۲ کالای الف را میخرد. بنابراین در جدول فروش, چهار مقدار ثبت شده است که هر کالا به دو مشتری و هر مشتری به دو کالا مرتبط شده است. در اینجا جدول فروش, به عنوان جدول ثالث است.
برای پیاده سازی ارتباط One to One, در مرحله اول یک مدل جدید ایجاد میکنیم:
@Entity public class Company { @Id @GeneratedValue private int id; private String name; private String address; }
سپس این Entity را به User Entity اضافه میکنیم:
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private String name; @OneToOne(cascade = CascadeType.ALL) private Company company; }
وقتی از cascade استفاده میکنیم که میخواهیم به Hibernate اطلاع دهیم, این مقدار را همراه با والد خود(که در اینجا User است) ذخیره کند. در غیر این صورت با این خطا مواجه میشویم:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance beforeQuery flushing
با اجرای کد فوق, یک جدول به نام شرکت ایجاد میشود و دو سطر جدول از طریق شناسه جدول شرکت, به یکدگیر مرتبط میشوند.
برای پیاده سازی One to Many Relation باید مقدار مورد نظر را از نوع Collection انتخاب کنیم. به این ترتیب کلاس User را به این صورت تغییر میدهیم:
public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; private String name; @OneToMany(cascade = CascadeType.ALL) @JoinColumn(name = "com_fk") private Collection<Company> company = new ArrayList<>(); }
در جدول Company یک ستون ایجاد میشود و مقدار شناسه کاربر را نگهداری میکند.
برای پیاده سازی Many to Many Relation نیز هر دو کلاس را به صورت Collation در میآوریم. در کلاس User این تغییرات را بوجود میآوریم:
@JoinTable(name = "comp_user_fk",joinColumns = @JoinColumn(name = "company_id")) private Collection<Company> company = new ArrayList<>();
و کلاس Company را به این صورت تغییر میدهیم:
@ManyToMany(mappedBy = "company") private List<User> userList=new ArrayList<>();
اکنون mapping بر اساس company انجام میشود. حتما باید از join table annotation استفاده شود و جدول ثالث را از این طریق مشخص میکنیم.
در این مقاله سعی بر این شد تا مفهوم Relation Mapping را مورد بررسی قرار دهیم و به پیاده سازی آنها در Hibernate بپردازیم.
سری مقالات آموزش Java Enterprise ادامه دارد.
با ما همراه باشید.
دیدگاهتان را بنویسید
برای نوشتن دیدگاه باید وارد بشوید.