Salut,
Sur mon temps libre, j'ai essayé d'utiliser la méthode merge d'hibernate
pour simplifier les problématiques de mises à jour de collection en
cascade depuis une composition (ajout/suppression/modification) sans
avoir à le faire à la main.
La méthode merge[1] est un peu différente de saveOrCreate[2] et permet
de pouvoir rattacher les objets correctement et d'éviter les problèmes
sur les cascade. En effet, la méthode update pose problème sur les
objets modifiés en cascade (déjà rattaché à la session) et n'effectue
pas les suppressions. Un post intéressant sur les différences : [3]
Le seul souci dans Topia, c'est que les topiaId sont générés sur la
méthode create des DAO. Mais vu que dans ce cas les créations se font en
cascade, on ne passe pas par la méthode create.
Deux solutions :
- soit appeler la méthode create sur toute les nouvelles entités (cela
reviendrait à parcourir toute la collection à mettre à jour...)
- soit utiliser un autre mécanisme pour générer le topiaId. (via un
IdentifierGenerator[4] ou un listener sur le persist/merge[5]). Avec
hibernate pur, le IdentifierGenerator semble plus approprié. En JPA on
peut cependant utiliser le PrePersist pour générer le topiaId. Chose
étrange, en hibernate pur, le merge n'envoie pas d'évènement prePersist
pour les nouvelles entités, contrairement à la spec JPA.
Ci-joint un patch qui implémente la solution du IdentifierGenerator.
Cela implique :
- modification des mappings générés pour préciser le generator
- ajout du generator appliqué au contexte du modèle pour pouvoir
récupérer les interfaces des entités simplement avec le TopiaEntityEnum.
Le MergeTest illustre les deux cas d'utilisations possibles :
- depuis une entité non chargé dans hibernate (newInstance)
- depuis une entité chargé dans hibernate (findByTopiaId)
Les avantages :
- plus besoin de gérer manuellement les merge de collection
- la génération du topiaId est intégré aux mécanismes du framework
sous-jacent
Les inconvénients :
- aucun, la génération du topiaId est transparente et ne casse pas la
compatibilité avec l'existant
Reste à ajouter une méthode merge dans le DAO si cette idée/solution
vous semble intéressante à intégrer pour l'évolution de la librairie.
Quand pensez-vous ?
[1]
http://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/Session.htm…
[2]
http://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/Session.htm…
[3]
http://www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate/
[4]
http://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/id/Identifi…
[5] http://www.objectdb.com/java/jpa/persistence/event
PS : pour appliquer le patch à la racine du projet topia :
patch -p1 -i 0001-Add-merge-test.patch
Bonjour,
Depuis une version récente de isis, il semble y avoir un bug
de lazy avec des équations pendant les exports.
<many-to-one name="maturityOgiveEquation" />
J'ai l'impression que ca fonctionnait avant, maintenant, ca renvoie
un proxy javassist sur une equation, et lorsqu'on y accède, il n'y
a plus de session et ca cause une erreur :(
Je n'ai pas trop envie de mettre des tagvalue lazy = false
sur toutes les equations, mais je ne voit pas trop d'autres solution.
(car cette solution fonctionne).
Ce qui m'embête, c'est que cela ne faisait pas ca avant...
Regression topia? hibernate ?
--
Éric Chatellier <chatellier(a)codelutin.com>
Tel: 02.40.50.29.28
http://www.codelutin.com