-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Interceptor doesn't work on Many-to-Many associations
PostPosted: Tue Jan 26, 2010 6:22 am 
Newbie

Joined: Tue Sep 29, 2009 7:42 am
Posts: 6
I implemented a Hibernate Interceptor designed for auditing but the onFlushDirty() method does not seem to be invoked for the following scenario (simplified without the @JoinTable shown):

Code:
@Entity
class A
{
  @ManyToMany
  public Set<B> getBs() { .... };
}

@Entity
class B
{
  @ManyToMany(mappedBy="bs")
  public Set<A> getAs() { .... };
}


Code:
A a = session.get(...);
B b = session.get(...);
a.getBs().remove(b);


Although b is correctly removed from the many-to-many table that maps between a and b, the onFlushDirty() method of the interceptor is NOT called, as I expected, on the entity A. Is this behavior normal / intended, because there is no in-between entity class defined for the @JoinTable between A and B?


Top
 Profile  
 
 Post subject: Re: Interceptor doesn't work on Many-to-Many associations
PostPosted: Wed Jan 27, 2010 9:18 am 
Regular
Regular

Joined: Thu Sep 06, 2007 2:22 am
Posts: 108
Location: Noida,India
Could you pls post your interceptor code


Top
 Profile  
 
 Post subject: Re: Interceptor doesn't work on Many-to-Many associations
PostPosted: Wed Jan 27, 2010 12:32 pm 
Newbie

Joined: Tue Sep 29, 2009 7:42 am
Posts: 6
Hi parmendratyagi, thanks for responding. The structure of my interceptor is similar to what is shown below. However, a bit of research revealed to me that I should have implemented one of the onCollection methods (probably onCollectionUpdate?) defined by the Interceptor interface (https://www.hibernate.org/hib_docs/v3/a ... eptor.html). Most of the auditing examples I've seen so far did not implement those methods. I'll investigate further and post more results later.

Code:
public class LoggedInterceptor extends EmptyInterceptor {
   
   @Override
    public boolean onSave( Object entity, Serializable id, Object[] state,
        String[] propertyNames, Type[] types ) throws CallbackException
    {
       System.out.println("A "+entity.getClass().getCanonicalName() + " was created.");
       return false;
    }
   
    @Override
    public boolean onFlushDirty( Object entity, Serializable id,
        Object[] currentState, Object[] previousState, String[] propertyNames,
        Type[] types )
    {
       System.out.println("A "+entity.getClass().getCanonicalName() + " was updated.");
       return false;
    }
   
    @Override
    public void onDelete( Object entity, Serializable id, Object[] state,
        String[] propertyNames, Type[] types )
    {
       System.out.println( "A " +entity.getClass().getCanonicalName() + " was deleted.");
    }

}


Top
 Profile  
 
 Post subject: Re: Interceptor doesn't work on Many-to-Many associations
PostPosted: Wed Jan 27, 2010 10:36 pm 
Newbie

Joined: Tue Sep 29, 2009 7:42 am
Posts: 6
A previous forum post from https://forum.hibernate.org/viewtopic.php?f=1&t=979340 pointed me in the right direction. Based on the API for onCollectionUpdate:

Code:
onCollectionUpdate(Object collection, Serializable key)


collection always appears to be of type PersistentCollection (I'm not sure why the API does not simply specify this type in the method argument), and key seems to refer to the @Id of the owning entity.

When cast as a PersistentSet which implements the java.util.Set interface, collection behaves as a normal Java collection containing the new values. The old values can be obtained by invoking collection.getStoredSnapshot() which (in my case at least) returns a java.util.HashMap.

I'm not sure why a HashMap is returned when a simple List-type collection would suffice. Examining the contents of the HashMap show key-value pairs where key = value. In any case, I am now able to get both the old and new values, and determine a delta from there.


Top
 Profile  
 
 Post subject: Re: Interceptor doesn't work on Many-to-Many associations
PostPosted: Thu Jan 28, 2010 2:23 am 
Newbie

Joined: Tue Sep 29, 2009 7:42 am
Posts: 6
The following code below (added to any class extending EmptyInterceptor) seems to be sufficient in logging changes to Sets, although it could also be changed to work for Collections in general. Hopefully this code will also be useful to others who are creating their own interceptors.

Code:
    @Override
    public void onCollectionUpdate(Object collection, Serializable key)
    {
       
       if (collection instanceof PersistentSet)
       {
          PersistentSet newValues = (PersistentSet) collection;          
          Object owner = newValues.getOwner();
          
          Set<?> oldValues = ((Map<?,?>) newValues.getStoredSnapshot()).keySet();
          
          System.out.println(owner + " had one of its collections changed.");
          System.out.println("The collection property is "+ newValues.getRole().replace(owner.getClass().getCanonicalName() + ".", "") );
          
          // find all objects that were added
          for (Object newValue : newValues)
          {
             if (!oldValues.contains(newValue))
             {
                System.out.println("A " + newValue + " was added.");
             }
          }
          
          // find all objects that were deleted
          for (Object oldValue : oldValues)
          {
             if (!newValues.contains(oldValue))
             {
                System.out.println("A " + oldValue + " was removed.");
             }
          }
          
       }
       
    }


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.