How to detect collection changes in a Hibernate PostUpdateEventListener?

In Hibernate, the PostUpdateEventListener implementation allows you to plug in a Hibernate workflow and gives you the ability to check and compare old and new values ​​of Entity properties as they are saved ( PostUpdateEvent has getOldState () and getState () methods that return an array of these values). For standard properties, this works fine. However, if one of these properties is a collection whose contents have changed, this will not help: the "old value" and "new value" are the same reference to the collection (since the collection itself has not changed, just its contents). This means that you can only see the last "new" content of this collection.

Does anyone know if there is a way to determine how the elements of a collection owned by Entity changed at this point in the workflow?

+3
source share
2 answers

I figured out a way to do this, so I will post it in case it will be used by anyone else. This code skips all the properties of the "old state" and for any permanent collections receives a "snapshot" of the previous content. He then wraps it in an unmodifiable collection for good measure:

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
  }   
+6
source

It seems that the interface is for collecting collection changes.

Implementing a complete audit trail

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

Source: https://habr.com/ru/post/1707486/


All Articles