有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

如何检查Hibernate中的实体是否处于脏状态?也就是说,我只想在某些字段发生更改时设置UpdatedByUpdatedAt。因此,我可以手动执行对象检查,比较两个对象中的每个字段,但是否有更优雅的方法来执行此操作

另外,若我将对象的字段设置为和以前相同的值,hibernate是否会使实体dirty?即:

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

编辑:

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


共 (2) 个答案

  1. # 1 楼答案

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

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

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

  2. # 2 楼答案

    这是一个非常好的问题,这是一个简短的答案:Hibernate会话有一个方法isDirty()

    用示例详细回答(测试用例1):

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

    您知道Hibernate会话有一个方法isDirty(),但在某些情况下,这是不够的

    您可以在持久性中注册一个Hibernate拦截器。xml文件:

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

    截取方法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);  
         }  
    ...  
    }  
    

    解决此测试用例: 如果只需要更新实体,则不需要知道哪些实体发生了更改。您可以在@PreUpdate方法中添加代码(填充更改代码的用户)。脏的实体将被相应地修改,不脏的实体将不会调用此方法,因为没有要更新的内容(Hibernate将检测到)。您可以对@PrePersist方法中的新实体执行相同的操作,该方法可能是相同的。您可以用这两种方法注释相同的方法

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