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?
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.
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.
Ceci est bien illustré par le documentation Doctrine ORM de l'Association Mapping (je ne pense pas que cela soit spécifique à Hibernate).
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);
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.
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
.