web-dev-qa-db-fra.com

Hibernate ManyToOne vs OneToOne

Je ne vois aucune différence entre le schéma d'une relation plusieurs-à-un et une relation OneToOne:

@Entity
public class Order {

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

contre

@Entity
public class Order {

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

Y a-t-il une différence?

34
DD.

Ils ont exactement la même apparence sur le schéma mais il y a une différence sur la couche Hibernate.

Si vous essayez quelque chose comme ça:

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

Tout va bien se passer. Mais, après la sauvegarde, si vous essayez d’obtenir l’ordre:

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

@ManyToOne case:
SUCCESS

Bien entendu, votre classe d’adresses doit être différente dans les deux cas.

33
paulek

Il devrait normalement y avoir une contrainte unique sur la colonne de jointure address_id dans le cas d'une association OneToOne, afin de garantir qu'un seul Ordre puisse avoir une adresse donnée.

5
JB Nizet

Ceci est bien illustré par le documentation Doctrine ORM de l'Association Mapping (je ne pense pas que cela soit spécifique à Hibernate). 

ManyToOne:

Considérez les tables User et Address tandis que la colonne User.address_id a une association ManyToOne avec la colonne Address.id. Ce serait le 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); 

Un par un:

Maintenant, considérons les tables Product et Shipment, tandis que la colonne Product.shipment_id possède une association OneToOne (unidirectionnelle) avec la colonne Shipment.id. Ce serait le 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);

La différence est la clause UNIQUE INDEX qui indique qu'il ne doit pas y avoir de shipment.id survenant deux fois dans la table Product. Cela garantit l'association One ToOne.

0
agoldev

Cela indique que les deux côtés de la relation sont mieux servis en ayant la même clé primaire. Il a plus de sens ainsi puisque les deux côtés sont associés un et un seul ordre dans le cas de la relation @OneToOne.

0
Progster219