web-dev-qa-db-fra.com

Comment vérifier si l'entité dans Hibernate est sale?

Comment vérifier si l'entité en veille prolongée est dans un état sale? C'est à dire. Je veux définir UpdatedBy et UpdatedAt uniquement si certains champs ont changé. Je peux donc faire une vérification d'objet en comparant manuellement chaque champ en 2 objets, mais peut-être existe-t-il une manière plus élégante de le faire?

En outre, hibernate fait-il l'entité dirty si je mets au champ d'objet la même valeur qu'auparavant? C'est à dire.:

String name = myEntity.getName()
myEntity.setName(name);

MODIFIER:

Mais j'ai aussi un autre problème - j'ai une entité avec des collections imbriquées, donc si n'a changé que l'élément de cette collection, alors je veux définir UpdatedBy uniquement sur cet élément de collection, mais pas sur l'objet qui possède cette collection. Je fais des mises à jour en utilisant des opérations en cascade.

22
MyTitle

Est une excellente question, voici la réponse courte: Hibernate-Session a une méthode isDirty ()

Réponse longue avec exemple (CAS D'ESSAI 1):

Si vous utilisez Seam/POJO/JPA sur Hibernate. vous souhaitez savoir quelles entités sont sales avant d'appeler entityManager.flush () - c'est-à-dire savoir pour quelles entités Hibernate émettrait une instruction de mise à jour - et appliquer certaines modifications à ces enregistrements (définir des valeurs comme qui a modifié l'enregistrement, etc.) .

vous savez que la session Hibernate a une méthode isDirty (), mais cela ne suffit pas dans certains cas.

vous pouvez enregistrer un Hibernate-Interceptor dans votre fichier persistence.xml

     <property name="hibernate.ejb.interceptor" value="path.to.MyInterceptor" />  

et intercepter la méthode onFlushDirty (...) et enregistrer les objets sales dans une carte, mais comment puis-je accéder à cette carte plus tard? Je n'ai pas accès à l'intercepteur lors de l'exécution (pour pouvoir appeler interceptor.getDirtyEntities ()), vous avez ceci:

public class MyInterceptor extends EmptyInterceptor {  
         private Map<IdentityKey,Object> dirtyEntitiesMap = new HashMap<IdentityKey,Object>();  

     @Override  
     public boolean onFlushDirty(Object entity, Serializable id,  
               Object[] currentState, Object[] previousState,  
               String[] propertyNames, Type[] types) {  

           dirtyEntitiesMap.put(new IdentityKey(id, entity.getClass()), entity);    
           return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types);  
     }  
...  
}  

RÉSOUDRE CE CAS D'ESSAI: Vous n'avez pas besoin de savoir quelles entités changent si vous avez seulement besoin de les mettre à jour. Vous pouvez ajouter votre code (en remplissant l'utilisateur qui les a modifiés) dans une méthode @PreUpdate. Les entités qui sont sales seront modifiées en conséquence, celles qui ne le seront pas ne recevront pas cette méthode car il n'y a rien à mettre à jour (et Hibernate le détectera). Vous pouvez faire de même pour les nouvelles entités dans une méthode @PrePersist qui est probablement identique. Vous pouvez annoter la même méthode avec les deux.

Si vous devez également enregistrer les champs qui ont été modifiés, je vous suggère de regarder d'abord Envers.

8
tomj0101

la méthode onFlushDirty (...) fonctionne pour moi pour vérifier la collection sale. L'entité parent avec la collection imbriquée est passée dans onFlushDirty, mais je ne savais pas que l'entité transmise pouvait être l'élément de collection. Une fois que j'ai trouvé cela, cela a fonctionné à la fois pour la collection imbriquée et son entité parent.

public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types)

Une autre méthode, onCollectionUpdate (...), peut également être utilisée pour intercepter une collection sale, elle est appelée après onFlushDirty (...).

0
user3325137William