Quelqu'un sait-il comment Hibernate sait s'il faut INSÉRER ou METTRE À JOUR une valeur dans la base de données lorsque session.saveOrUpdate()
est appelée?
Jusqu'à présent, j'ai uniquement déterminé que cela ne dépend pas des informations contenues dans le cache et que l'existence de l'entité dans la base de données est déterminée par la clé primaire.
Lorsque vous utilisez .saveOrUpdate()
Hibernate vérifiera si l'objet est transitoire (il n'a pas de propriété d'identifiant) et si c'est le cas, il le rendra persistant en lui générant l'identifiant et en l'affectant à la session. Si l'objet a déjà un identifiant, il exécutera .update()
.
De la documentation :
saveOrUpdate () effectue les opérations suivantes:
Il est peut-être utile de citer la Bible Hibernate ( Java Persistence with Hibernate, 2nd ed. , page 528):
Les utilisateurs d'Hibernate plus expérimentés utilisent exclusivement
saveOrUpdate()
; il est beaucoup plus facile de laisser Hibernate décider ce qui est nouveau et ce qui est ancien, en particulier dans un réseau plus complexe d'objets à état mixte. Le seul inconvénient (pas vraiment sérieux) de l'exclusifsaveOrUpdate()
est qu'il ne peut parfois pas deviner si une instance est ancienne ou nouvelle sans tirer unSELECT
sur la base de données - par exemple, lorsqu'une classe est mappé avec une clé composite naturelle et aucune propriété de version ou d'horodatage.Comment Hibernate détecte-t-il les instances anciennes et les nouvelles? Une gamme d'options est disponible. Hibernate suppose qu'une instance est une instance transitoire non enregistrée si:
- La propriété d'identifiant est
null
.- La propriété de version ou d'horodatage (si elle existe) est
null
.- Une nouvelle instance de la même classe persistante, créée par Hibernate en interne, a les mêmes valeurs d'identifiant de base de données que l'instance donnée.
- Vous fournissez un
unsaved-value
Dans le document de mappage pour la classe, et la valeur de la propriété d'identificateur correspond. L'attributunsaved-value
Est également disponible pour les éléments de mappage de version et d'horodatage.- Les données d'entité avec la même valeur d'identifiant ne sont pas dans le cache de deuxième niveau.
- Vous fournissez une implémentation ou
org.hibernate.Interceptor
Et renvoyezBoolean.TRUE
À partir deInterceptor.isUnsaved()
après avoir vérifié l'instance dans votre code.
Comme indiqué ici , saveOrUpdate
enregistre une instance transitoire en générant un nouvel identifiant ou met à jour/rattache les instances détachées associées à son identifiant actuel. Plus précisément, il le fait:
save()
it<version>
ou <timestamp>
, et que la valeur de la propriété version estsave()
ilupdate()
l'objetSi quelqu'un n'est pas vraiment compris en théorie, il y a un code
MyModel sent = myDao.myDaoImpl(id);
if(sent == null){
sent = **new MyModel();** // new Object
sent.setXX(id);
sent.setYY("Yes");
sent.setDate(new Date());
myDao.saveOrUpdate(sent); // Insert will be called
} else if(! "Yes".equalsIgnoreCase(sent.getFlag())) {
sent.setXX("Yes");
sent.setDate(new Date());
myDao.saveOrUpdate(sent); // Update will be called
}
Cela se fait en fonction de la valeur de la clé primaire. Si la clé primaire n'est pas définie, sa valeur par défaut sera 0 pour les clés de substitution numériques et save
sera exécuté. Si la clé primaire est remplie, elle invoquera un update
.