Cascade - erreur courante d'annotation JPA et Hibernate
Souvent, les développeurs utilisent ensemble l'annotation JPA et Hibernate ensemble, cela causera une erreur très courante - l'annotation de type cascade JPA ne fonctionne pas dans Hibernate?
Au cours de la section de révision du code, je découvre que de nombreux développeurs Java ne sont pas conscients de cette erreur et que le programme n'a pas réussi à exécuter l'opération en cascade vers les entités associées. Je prendrai cesone-to-many hibernate example pour la démonstration.
Erreur
Dans l'exemple un à plusieurs, de nombreux développeurs ont déclaré les options de cascade JPA comme suit:
... @Entity @Table(name = "stock", catalog = "example", uniqueConstraints = { @UniqueConstraint(columnNames = "STOCK_NAME"), @UniqueConstraint(columnNames = "STOCK_CODE") }) public class Stock implements java.io.Serializable { ... private SetstockDailyRecords = new HashSet (0); @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST,CascadeType.MERGE }, mappedBy = "stock") public Set getStockDailyRecords() { return this.stockDailyRecords; } public void setStockDailyRecords(Set stockDailyRecords) { this.stockDailyRecords = stockDailyRecords; } ...
Enregistrez-le avec la session Hibernate.
stockDailyRecords.setStock(stock); stock.getStockDailyRecords().add(stockDailyRecords); session.save(stock); session.getTransaction().commit();
Ce que le code essaie de faire, c'est que lorsque vous enregistrez un «stock», il enregistrera également les stockDailyRecords associés. Tout semble correct, maisTHIS IS NOT WORKING, les options en cascade ne s'exécuteront pas et ne sauveront pas les stockDailyRecords. Pouvez-vous repérer l'erreur?
Explication
Regardez dans le code,@OneToMany vient de JPA, il s'attendait à une cascade JPA -javax.persistence.CascadeType. Cependant, lorsque vous l'enregistrez avec la session Hibernate,org.hibernate.engine.Cascade effectuera la vérification suivante…
if ( style.doCascade( action ) ) { cascadeProperty( persister.getPropertyValue( parent, i, entityMode ), types[i], style, anything, false ); }
Le processus de sauvegarde Hibernate provoquera une actionACTION_SAVE_UPDATE, mais le JPA passera unACTION_PERSIST et unACTION_MERGE, il ne correspondra pas et la cascade n'a pas pu s'exécuter.
@see code source
-
org.hibernate.engine.Cascade
-
org.hibernate.engine.CascadeStyle
-
org.hibernate.engine.CascadingAction
Solution
Supprimez la cascade JPA -javax.persistence.CascadeType, remplacez-la par cascade Hibernate -org.hibernate.annotations.Cascade, parCascadeType.SAVE_UPDATE.
... @Entity @Table(name = "stock", catalog = "example", uniqueConstraints = { @UniqueConstraint(columnNames = "STOCK_NAME"), @UniqueConstraint(columnNames = "STOCK_CODE") }) public class Stock implements java.io.Serializable { ... private SetstockDailyRecords = new HashSet (0); @OneToMany(fetch = FetchType.LAZY, mappedBy = "stock") @Cascade({CascadeType.SAVE_UPDATE}) public Set getStockDailyRecords() { return this.stockDailyRecords; } public void setStockDailyRecords(Set stockDailyRecords) { this.stockDailyRecords = stockDailyRecords; } ...
Maintenant, cela fonctionne comme prévu.
Conclusion
Cela ressemble à un problème incompatible entre JPA et l'annotation en cascade Hibernate.Si Hibernate est une implémentation JPA, qu'est-ce qui peut provoquer le malentendu entre les deux?