STACKJAVA

So sánh sự khác nhau giữa @OneToOne với @ManyToOne Hibernate

So sánh sự khác nhau giữa @OneToOne với @ManyToOne Hibernate.

(Xem thêm: Hướng dẫn tự học Hibernate)

 

Quan hệ 1-1 và 1-n trong SQL

Ví dụ 1:

Quan hệ giữa item_detail với item là 1-1

DROP TABLE IF EXISTS `item`;
CREATE TABLE `item` (
  `id` int(11) NOT NULL,
  `name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
);


DROP TABLE IF EXISTS `item_detail`;
CREATE TABLE `item_detail` (
  `id` int(11) NOT NULL,
  `description` varchar(45) DEFAULT NULL,
  `vendor` varchar(45) DEFAULT NULL,
  `remark` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `item-detail` FOREIGN KEY (`id`) REFERENCES `item` (`id`)
);

Trong mối quan hệ trên, item_detail mapping với item qua chính id của nó tức là item_detailitem có giá trị id giống nhau

Ví dụ 2:

Quan hệ giữa item_detail với item là 1-1

DROP TABLE IF EXISTS `item`;
CREATE TABLE `item` (
  `id` int(11) NOT NULL,
  `name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

DROP TABLE IF EXISTS `item_detail`;
CREATE TABLE `item_detail` (
  `id` int(11) NOT NULL,
  `item_id` int(11) DEFAULT NULL,
  `description` varchar(45) DEFAULT NULL,
  `vendor` varchar(45) DEFAULT NULL,
  `remark` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `item_id_UNIQUE` (`item_id`),
  CONSTRAINT `item-detail` FOREIGN KEY (`item_id`) REFERENCES `item` (`id`)
);

Trong mối quan hệ trên, item_detail mapping với item qua column item_id của nó tức là item_detail.item_iditem.id có giá trị id giống nhau

Lưu ý, column item_id sẽ là UNIQUE KEY, tức là sẽ không xảy ra trường hợp có nhiều row trong item_detail có cùng giá trị item_id

Ví dụ 3:

Quan hệ giữa item_detail với item là n-1.

DROP TABLE IF EXISTS `item`;
CREATE TABLE `item` (
  `id` int(11) NOT NULL,
  `name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

DROP TABLE IF EXISTS `item_detail`;
CREATE TABLE `item_detail` (
  `id` int(11) NOT NULL,
  `item_id` int(11) DEFAULT NULL,
  `description` varchar(45) DEFAULT NULL,
  `vendor` varchar(45) DEFAULT NULL,
  `remark` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `item-detail` FOREIGN KEY (`item_id`) REFERENCES `item` (`id`)
);

Ví dụ 3 khá giống với ví dụ 2, item_detail mapping với item qua column item_id nhưng item_id không phải là UNIQUE_KEY, tức là có thể nhiều row item_detail cùng mapping tới 1 item.

Như vậy điểm khác nhau cơ bản giữa quan hệ 1-1 (OneToOne) với n-1 (ManyToOne) đó là quan hệ 1-1 chỉ cho phép 1 bản ghi chỉ được tham chiếu bởi 1 bản ghi khác trong khi quan hệ n-1 thì cho phép nhiều bản ghi cùng tham chiếu tới 1 bản ghi.

@ManyToOne và @OneToOne trong Hibernate

Khi mapping ví dụ trên sang Hibernate ta sẽ có kết quả sau:

Trường hợp OneToOne 1-1:

@Entity
public class ItemDetail {

    @OneToOne
    @JoinColumn(name = "item_id")
    // or @PrimaryKeyJoinColumn cho trường hợp dùng chung Id
    private Item item;

Trường hợp ManyToOne n-1:

@Entity
public class ItemDetail {

    @ManyToOne
    @JoinColumn(name = "item_id")
    private Item item;

 

2 trường hợp trên chỉ khác nhau ở annotation @OneToOne với @ManyToOne, nhưng khi insert sẽ khác nhau, ví dụ:

Item item = new Item();

ItemDetail itemDetail1 = new ItemDetail();
itemDetail1.setItem(item);

ItemDetail itemDetail2 = new ItemDetail();
itemDetail2.setItem(item);

save();

Đoạn code trên sẽ thành công với trường hợp ManyToOne

Nhưng với trường hợp OneToOne sẽ bị lỗi ConstraintViolationException do có nhiều hơn 1 ItemDetail tham chiếu tới 1 Item

 

________________

Okay, Done!

 

References:

https://stackoverflow.com/…manytoone-vs-onetoone