Ce contenu n'est pas disponible dans la langue sélectionnée.
21.2. Bidirectional one-to-many
Suppose we start with a simple
<one-to-many> association from Parent to Child.
<set name="children">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
<set name="children">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
If we were to execute the following code:
Parent p = .....; Child c = new Child(); p.getChildren().add(c); session.save(c); session.flush();
Parent p = .....;
Child c = new Child();
p.getChildren().add(c);
session.save(c);
session.flush();
Hibernate would issue two SQL statements:
- an
INSERTto create the record forc - an
UPDATEto create the link fromptoc
This is not only inefficient, but also violates any
NOT NULL constraint on the parent_id column. You can fix the nullability constraint violation by specifying not-null="true" in the collection mapping:
<set name="children">
<key column="parent_id" not-null="true"/>
<one-to-many class="Child"/>
</set>
<set name="children">
<key column="parent_id" not-null="true"/>
<one-to-many class="Child"/>
</set>
However, this is not the recommended solution.
The underlying cause of this behavior is that the link (the foreign key
parent_id) from p to c is not considered part of the state of the Child object and is therefore not created in the INSERT. The solution is to make the link part of the Child mapping.
<many-to-one name="parent" column="parent_id" not-null="true"/>
<many-to-one name="parent" column="parent_id" not-null="true"/>
You also need to add the
parent property to the Child class.
Now that the
Child entity is managing the state of the link, we tell the collection not to update the link. We use the inverse attribute to do this:
<set name="children" inverse="true">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
<set name="children" inverse="true">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
The following code would be used to add a new
Child:
Only one SQL
INSERT would now be issued.
You could also create an
addChild() method of Parent.
public void addChild(Child c) {
c.setParent(this);
children.add(c);
}
public void addChild(Child c) {
c.setParent(this);
children.add(c);
}
The code to add a
Child looks like this:
Parent p = (Parent) session.load(Parent.class, pid); Child c = new Child(); p.addChild(c); session.save(c); session.flush();
Parent p = (Parent) session.load(Parent.class, pid);
Child c = new Child();
p.addChild(c);
session.save(c);
session.flush();