21.2. un-vers-plusieurs bidirectionnel

Supposons que nous ayons une simple association <one-to-many> de Parent vers Child.

<set name="children">
    <key column="parent_id"/>
    <one-to-many class="Child"/>
</set>

Si nous executions le code suivant

Parent p = .....;
Child c = new Child();
p.getChildren().add(c);
session.save(c);
session.flush();

Hibernate exécuterait deux ordres SQL:

Ceci est non seuleument inefficace, mais viole aussi toute contrainte NOT NULL sur la colonne parent_id. Nous pouvons réparer la contrainte de nullité en spécifiant not-null="true" dans le mapping de la collection :

<set name="children">
    <key column="parent_id" not-null="true"/>
    <one-to-many class="Child"/>
</set>

Cependant ce n'est pas la solution recommandée.

La cause sous jacente à ce comportement est que le lien (la clé étrangère parent_id) de p vers c n'est pas considérée comme faisant partie de l'état de l'objet Child et n'est donc pas créé par l'INSERT. La solution est donc que ce lien fasse partie du mapping de Child.

<many-to-one name="parent" column="parent_id" not-null="true"/>

(Nous avons aussi besoin d'ajouter la propriété parent dans la classe Child).

Maintenant que l'état du lien est géré par l'entité Child, nous spécifions à la collection de ne pas mettre à jour le lien. Nous utilisons l'attribut inverse.

<set name="children" inverse="true">
    <key column="parent_id"/>
    <one-to-many class="Child"/>
</set>

Le code suivant serait utilisé pour ajouter un nouveau Child

Parent p = (Parent) session.load(Parent.class, pid);
Child c = new Child();
c.setParent(p);
p.getChildren().add(c);
session.save(c);
session.flush();

Maintenant, seul un INSERT SQL est nécessaire !

Pour alléger encore un peu les choses, nous devrions créer une méthode addChild() dans Parent.

public void addChild(Child c) {
    c.setParent(this);
    children.add(c);
}

Le code d'ajout d'un Child serait alors

Parent p = (Parent) session.load(Parent.class, pid);
Child c = new Child();
p.addChild(c);
session.save(c);
session.flush();