如何在Hibernate PostUpdateEventListener中确定集合更改?

时间:2009-05-01 17:29:51

标签: hibernate

在Hibernate中,实现 PostUpdateEventListener 允许您插入Hibernate的工作流程,并让您有机会在保存实体属性时检查和比较新旧值( PostUpdateEvent 包含返回这些值数组的方法 getOldState() getState()。对于标准属性,这很好用。但是,如果其中一个属性是其内容已更改的集合,则没有任何帮助:“旧值”和“新值”都是对集合的相同引用(因为集合本身没有改变,只是它的内容)。这意味着您只能看到该集合的最新内容,即“新”内容。

任何人都知道是否有办法确定实体拥有的馆藏元素在工作流程中此时的变化情况如何?

2 个答案:

答案 0 :(得分:6)

我找到了一种方法来做到这一点,所以我会发布它,以防其他人使用它。此代码循环遍历所有“旧状态”属性,对于任何持久集合,它将获取先前内容的“快照”。然后将它包装在一个不可修改的集合中,以便进行良好的测量:

public void onPostUpdate( PostUpdateEvent event )
{       
   for ( Object item: event.getOldState() )
   {
      Object previousContents = null;

      if ( item != null && item instanceof PersistentCollection )               
      {
         PersistentCollection pc = (PersistentCollection) item;
         PersistenceContext context = session.getPersistenceContext();            
         CollectionEntry entry = context.getCollectionEntry( pc );
         Object snapshot = entry.getSnapshot();

         if ( snapshot == null )
            continue;

         if ( pc instanceof List )
         {
            previousContents = Collections.unmodifiableList( (List) snapshot );
         }        
         else if ( pc instanceof Map )
         {
            previousContents = Collections.unmodifiableMap( (Map) snapshot );
         }
         else if ( pc instanceof Set )
         {  
            //Set snapshot is actually stored as a Map                
            Map snapshotMap = (Map) snapshot;
            previousContents = Collections.unmodifiableSet( new HashSet( snapshotMap.values() ) );          
         }
         else
           previousContents = pc;

      //Do something with previousContents here
  }   

答案 1 :(得分:2)

似乎有一个专门用于捕获集合更改的界面。

Audit Log implementation Full

 public void onPreUpdateCollection(PreCollectionUpdateEvent event) {
    if (bypass(event.getAffectedOwnerOrNull().getClass())) {
        return;
    }
    CollectionEntry collectionEntry = getCollectionEntry(event);    
 }


 protected CollectionEntry getCollectionEntry(AbstractCollectionEvent event) {
     return event.getSession().getPersistenceContext()
            .getCollectionEntry(event.getCollection());
 }