web-dev-qa-db-ja.com

ManyToOneとOneToOneの休止状態

多対1の関係とOneToOneの関係のスキーマに違いはありません。

@Entity
public class Order {

    @ManyToOne
    @JoinColumn(nullable = false)
    private Address address;

@Entity
public class Order {

    @OneToOne
    @JoinColumn(nullable = false)
    private Address address;

違いはありますか?

37
DD.

それらはスキーマではまったく同じに見えますが、Hibernateレイヤーでは違いがあります。

そのようなことをしようとすると:

Address address = new Address();
Order order1 = new Order();
order1.setAddress(address);
Order order2 = new Order();
order2.setAddress(address);
save();

すべて大丈夫です。しかし、保存してからOrderを取得しようとすると、次のようになります。

@OneToOne case:
org.hibernate.HibernateException: More than one row with the given identifier was found: 1

@ManyToOne case:
SUCCESS

もちろん、Addressクラスはどちらの場合でも異なって見えるはずです。

40
paulek

OneToOneアソシエーションの場合、通常、address_id結合列には一意の制約があり、1つのOrderのみが特定のアドレスを持つことができるようにする必要があります。

6
JB Nizet

これは 関連マッピングのDoctrine ORMドキュメント (Hibernateに固有のものではないと思います)でうまく説明されています。

ManyToOne:

User.address_idAddress.id列へのManyToOneアソシエーションがある間、テーブルUserおよびAddressを検討してください。これはSQLです。

CREATE TABLE User (
    id INT AUTO_INCREMENT NOT NULL,
    address_id INT DEFAULT NULL,
    PRIMARY KEY(id)
) ENGINE = InnoDB;

CREATE TABLE Address (
    id INT AUTO_INCREMENT NOT NULL,
    PRIMARY KEY(id)
) ENGINE = InnoDB;

ALTER TABLE User ADD FOREIGN KEY (address_id) REFERENCES Address(id); 

OneToOne:

ここで、テーブルProductおよびShipmentを検討します。一方、列Product.shipment_idには、Shipment.id列へのOneToOne(単方向)関連付けがあります。これはSQLです。

CREATE TABLE Product (
    id INT AUTO_INCREMENT NOT NULL,
    shipment_id INT DEFAULT NULL,
    UNIQUE INDEX UNIQ_6FBC94267FE4B2B (shipment_id),
    PRIMARY KEY(id)
) ENGINE = InnoDB;
CREATE TABLE Shipment (
    id INT AUTO_INCREMENT NOT NULL,
    PRIMARY KEY(id)
) ENGINE = InnoDB;
ALTER TABLE Product ADD FOREIGN KEY (shipment_id) REFERENCES Shipment(id);

違いは、ProductテーブルでUNIQUE INDEXが2回発生してはならないことを示すshipment.id句です。これにより、OneToOne関連付けが保証されます。

1
agoldev

これは、リレーションシップの両側が同じ主キーを持つことで最適に機能することを示しています。 @OneToOne関係の場合、両側が1つだけの注文に関連付けられるため、これは もっと理にかなっています この方法です。

0
Progster219