10.6. Modifier des objets détachés

Beaucoup d'applications ont besoin de récupérer un objet dans une transaction, l'envoyer à la couche interfacée avec l'utilisateur pour les manipulations, puis sauvegarder les changements dans une nouvelle transaction. Les applications qui utilisent cette approche dans un environnement à haute concurrence utilisent généralement des données versionnées pour assurer l'isolation pour les "longues" unités de travail.

Hibernate supporte ce modèle en permettant pour le réattachement d'instances détachées l'utilisation des méthodes Session.update() ou Session.merge() :

// in the first session
Cat cat = (Cat) firstSession.load(Cat.class, catId);
Cat potentialMate = new Cat();
firstSession.save(potentialMate);

// in a higher layer of the application
cat.setMate(potentialMate);

// later, in a new session
secondSession.update(cat);  // update cat
secondSession.update(mate); // update mate

Si le Cat avec l'identifiant catId avait déjà été chargé par secondSession lorsque l'application a essayé de le réattacher, une exception aurait été levée.

Utilisez update() si vous êtes sure que la session ne contient pas déjà une instance persistante avec le même identifiant, et merge() si vous voulez fusionner vos modifications n'importe quand sans considérer l'état de la session. En d'autres mots, update() est généralement la première méthode que vous devriez appeler dans une session fraîche, pour s'assurer que le réattachement de vos instances détachées est la première opération qui est exécutée.

L'application devrait individuellement update() (NdT : mettre à jour) les instances détachées accessibles depuis l'instance détachée donnée si et seulement si elle veut que leur état soit aussi mis à jour. Ceci peut être automatisé bien sûr, en utilisant la persistance transitive, voir Section 10.11, « Persistance transitive ».

La méthode lock() permet aussi à une application de réassocier un objet avec une nouvelle session. Pourtant, l'instance détachée doit être non modifiée !

//just reassociate:
sess.lock(fritz, LockMode.NONE);
//do a version check, then reassociate:
sess.lock(izi, LockMode.READ);
//do a version check, using SELECT ... FOR UPDATE, then reassociate:
sess.lock(pk, LockMode.UPGRADE);

Notez que lock() peut être utilisé avec différents LockModes, voir la documentation de l'API documentation et le chapitre sur la gestion des transactions pour plus d'informations. Le réattachement n'est pas le seul cas d'utilisation pour lock().

D'autres modèles pour de longues unités de travail sont traités dans Section 11.3, « Contrôle de consurrence optimiste ».