Java 如何检查 Hibernate 中的实体是否脏?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20393006/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 01:36:51  来源:igfitidea点击:

How to check if entity in Hibernate is dirty?

javahibernatejpaormjpa-2.0

提问by MyTitle

How to check if entity in Hibernate is in dirty state? I.e. I want do set UpdatedByand UpdatedAtonly if some field has changed. So I can do object check manually comparing each field in 2 objects, but may be there exist some more elegant way to do it?

如何检查 Hibernate 中的实体是否处于脏状态?即我想要设置UpdatedBy并且UpdatedAt仅当某些字段已更改时。因此,我可以手动比较 2 个对象中的每个字段进行对象检查,但是可能存在一些更优雅的方法吗?

Also, does hibernate makes entity dirtyif I set to object's field same value as it was before? I.e.:

另外,dirty如果我将对象的字段设置为与以前相同的值,hibernate 是否会生成实体?IE:

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

EDIT:

编辑:

But also I have another problem - I have entity with nested collections, so if has changed only element in that collection, then I want to set UpdatedBy only on that collection element, but not on object that owns this collection. I make updates using cascade operations.

但我还有另一个问题 - 我有嵌套集合的实体,所以如果只更改了该集合中的元素,那么我只想在该集合元素上设置 UpdatedBy,而不是在拥有该集合的对象上设置。我使用级联操作进行更新。

回答by tomj0101

Is a excellent, question, this is the short answer: Hibernate-Session has a method isDirty()

是一个很好的问题,这是简短的回答:Hibernate-Session has a method isDirty()

Long Answer with Example (TEST CASE 1):

带示例的长答案(测试案例 1):

If your are using Seam/POJOs/JPA on top of Hibernate. you would like to know wich entities are dirty before calling entityManager.flush() - i.e. know for which entities Hibernate would issue an update-statement - and apply some changes on these records (set some values like who changed the record and so on).

如果您在 Hibernate 之上使用 Seam/POJOs/JPA。您想在调用 entityManager.flush() 之前知道哪些实体是脏的 - 即知道 Hibernate 将针对哪些实体发出更新语句 - 并对这些记录应用一些更改(设置一些值,例如谁更改了记录等) .

you know that the Hibernate-Session has a method isDirty(), but this is not enough in some case.

你知道 Hibernate-Session 有一个方法 isDirty(),但在某些情况下这还不够。

you could register a Hibernate-Interceptor in you persistence.xml-file

你可以在你的persistence.xml文件中注册一个Hibernate-Interceptor

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

and intercept the method onFlushDirty(...) and save the dirty objects in a map but how can I access this map later on? I don't have access to the interceptor at runtime (so that I could call interceptor.getDirtyEntities()), you have this:

并拦截方法 onFlushDirty(...) 并将脏对象保存在地图中,但我以后如何访问该地图?我在运行时没有访问拦截器的权限(这样我就可以调用interceptor.getDirtyEntities()),你有这个:

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);  
     }  
...  
}  

SOLVER THIS TEST CASE: You don't need to know which entities changes if you only need to update those. You can add your code (populating the user who changed them) in a @PreUpdate method. The entities which are dirty will be modified accordingly, those that are not will not get this method called since there is nothing to update (and Hibernate will detect that). You can do the same for new entities in a @PrePersist method which is probably identical. You can annotate the same method with both.

解决这个测试案例:如果你只需要更新那些实体,你就不需要知道哪些实体发生了变化。您可以在 @PreUpdate 方法中添加您的代码(填充更改它们的用户)。脏的实体将被相应地修改,那些不是的将不会调用此方法,因为没有任何更新(并且 Hibernate 会检测到)。您可以在可能相同的 @PrePersist 方法中对新实体执行相同的操作。您可以使用两者注释相同的方法。

If you also need to record which fields have been changed, I'd suggest to look at Envers first.

如果您还需要记录哪些字段已更改,我建议您先查看 Envers。

回答by user3325137William

onFlushDirty(...) method works for me to check dirty collection. The parent entity with nested collection is passed into onFlushDirty, but I was not aware that the passed-in entity could be the collection element. Once I found that, it worked both for the nested collection and its parent entity.

onFlushDirty(...) 方法适用于我检查脏集合。带有嵌套集合的父实体被传递到 onFlushDirty,但我不知道传入的实体可能是集合元素。一旦我发现,它对嵌套集合及其父实体都有效。

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

Another method, onCollectionUpdate(...), also can be used to catch dirty collection, it gets called after onFlushDirty(...).

另一种方法 onCollectionUpdate(...) 也可用于捕获脏集合,它在 onFlushDirty(...) 之后调用。