2009-05-01 101 views
3

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

任何人都知道是否有方法可以确定工作流中此时实体拥有的集合的元素如何更改?

回答

6

我想出了一个办法来做到这一点,所以我会张贴它的使用情况下,其他人。此代码循环遍历所有“旧状态”属性,对于任何持久集合,都会获取以前的内容“快照”。然后它封装此不可修改的Collection好措施在:

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 
    } 
+0

你怎么比较集合?我没有看到'significantChange`方法足够了。 – 2012-08-14 14:55:20

1

似乎有一个接口专门用于捕捉收集相关的改变。

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