بسم الله الرحمن الرحیم
برای تعیین یک رابطه یک به یک باید یک ستون ارتباطی بین دو جدول داشته باشیم که به آن کلید خارجی می گویند.
یعنی در جدول مقصد یک کلید اصلی و یک کلید خارجی برای ارتباط با جدول مبدا خواهیم داشت .
چون رابطه یک به یک هست یعنی هر سطر از جدول مبدا فقط با یک سطر از جدول مقصد ارتباط دارد و نظیر به نظیر هستند . اگر بتوانیم کلید خارجی را در جدول مقصد حذف کنیم و فقط با همین کلید های اصلی ارتباط بین دو جدول را برقرار کنیم فواید خیلی زیادی حاصل خواهد شد .
در شکل زیر تفاوت دو روش را مشاهده می کنید :
در اینجا جدول پست دیتیلز با جدول پست به واسطه کلید خارجی
پست آیدی ارتباط یک به یک برقرار کرده است .
ولی در شکل زیر جدول پست دیتیلز فقط یک کلید دارد که از آن , هم به عنوان کلید اصلی و هم به عنوان کلید خارجی برای ارتباط با جدول پست استفاده شده است .
روش استفاده از فقط یک کلید هم به عنوان اصلی و هم برای ارتباط خیلی فواید زیادی دارد :
۱ - کاهش پیچیدگی و افزایش سادگی مدل داده:
در این روش شما میتوانید رابطه بین موجودیتها را به طور مستقیم و با استفاده از کلید اصلی (primary key) برقرار کنید. این روش باعث کاهش پیچیدگی در مدل داده میشود زیرا دیگر نیازی به تعریف کلید خارجی (foreign key) اضافی و نگهداری آن در جدول موجودیت فرزند نیست. به عبارت دیگر، کلید اصلی موجودیت فرزند به کلید اصلی موجودیت والد نگاشت میشود و این موضوع باعث میشود که مدل داده سادهتر و تمیزتری داشته باشید.
۲ - حفظ یکپارچگی دادهها:
باعث میشود که یکپارچگی دادهها (data integrity) بهتر حفظ شود. به عنوان مثال، در یک رابطه one-to-one، اگر کلید اصلی موجودیت والد تغییر کند، به طور خودکار کلید اصلی موجودیت فرزند نیز تغییر میکند. این رفتار باعث میشود که رابطه بین دو موجودیت همیشه معتبر باقی بماند و هیچگاه دادههای یتیم (orphan data) ایجاد نشود.
۳ - کاهش افزونگی دادهها:
نیازی به نگهداری یک ستون جداگانه برای کلید خارجی در موجودیت فرزند ندارید. یعنی اطلاعات اضافه و بی ارزش از بین می رود .
۴ - بهبود عملکرد و کارایی:
نگاشت کلید اصلی به کلید خارجی میتواند به بهبود عملکرد و کارایی برنامه کمک کند. زیرا در این روش، عملیات CRUD ( ایجاد، خواندن، بهروزرسانی و حذف) به صورت بهینهتری انجام میشود. به طور خاص، به دلیل کاهش نیاز به جداول واسط و کاهش تعداد جستجوها و بهروزرسانیها در پایگاهداده، عملکرد کلی برنامه بهبود مییابد.
این روش در اسپرینگ بوت جاوا با @MapsId یپاده سازی می شود.
در جدول مقصد , ستون ارتباطی را با این انوتیشن مشخص می کنیم .
پیاده سازی این روش برای کلاس جدول مبدا :
@Entity(name = '' Post '' ) @Table(name = '' post '' ) public class Post { @Id @GeneratedValue private Long id; @OneToOne(mappedBy = '' post '' ) private PostDetails details; }
پیاده سازی این روش برای کلاس جدول مقصد :
@Entity(name = ''PostDetails'') @Table(name = ''post_details'') public class PostDetails { @Id private Long id; @OneToOne @MapsId private Post post; }
باید دقت کنید که در کلاس جدول مقصد برای مشخص کردن شناسه نباید از
@GeneratedValue
استفاده کنیم چون قرار هست کلید اصلی به وسیله جدول مبدا و ارتباط اش مشخص شود یعنی شناسه را در جدول مقصد به صورت زیر تعریف کنید :
@Id private Long id;
ستون ارتباطی در جدول مقصد را به این صورت بنویسید :
@OneToOne @MapsId private Post post;
ستون ارتباطی در جدول مبدا را به این صورت بنویسید :
@OneToOne(mappedBy = ''post'') private PostDetails details;
جدول مبدا :
@Entity(name = ''Post'') @Table(name = ''post'') public class Post { @Id @GeneratedValue private Long id; @OneToOne(mappedBy = ''post'') private PostDetails details; }
جدول مقصد :
@Entity(name = ''PostDetails'') @Table(name = ''post_details'') public class PostDetails { @Id @GeneratedValue private Long id; @OneToOne @JoinColumn(name = ''post_id'') private Post post; }
همان طور که می بیند در روش قدیمی و بدون @MapsId هر جدول یک شناسه دارد چون در هر دو
@GeneratedValue
برای شناسه تعریف شده است و جدول مقصد علاوه بر کلید اصلی یک کلید خارجی هم خواهد داشت .
خروجی روش قدیمی :