-->
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.  [ 12 posts ] 
Author Message
 Post subject: How to know if an entity is dirty: Interceptor
PostPosted: Fri Jan 25, 2008 1:03 pm 
Newbie

Joined: Tue Dec 04, 2007 10:20 am
Posts: 13
Hi:

Before I update an entity from the database I want to know if it's dirty or not, and if it's not dirty I won't call the save method.

I've read around and I've seen that hibernate gives us an utility called Interceptor. In the book it appears a long class with onLoad, etc... methods for making a log, but I just want to see if the entity that i'm going to save into the database it's the same (without any change) than the entity which is stored in the database.

For doing that i've seen something like this:
Code:
public int[] findDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types)
{
}


Do I have to set all that information when I call a method like this or is there any hibernate feature that retrieves all the property names and types from the entity?

Thank you very much in advance


Top
 Profile  
 
 Post subject: Re: How to know if an entity is dirty: Interceptor
PostPosted: Sat Jan 26, 2008 1:19 pm 
Pro
Pro

Joined: Tue Jun 12, 2007 4:13 am
Posts: 209
Location: Berlin, Germany
afertel wrote:

Before I update an entity from the database I want to know if it's dirty or not, and if it's not dirty I won't call the save method.

I've read around and I've seen that hibernate gives us an utility called Interceptor. In the book it appears a long class with onLoad, etc... methods for making a log, but I just want to see if the entity that i'm going to save into the database it's the same (without any change) than the entity which is stored in the database.


Hi,

I think you have 2 choices: either you do the dirty checking BEFORE calling Hibernate to save your object, and then you have to write your own comparison. Or, you let just do Hibernate the job of finding out IF your object is dirty. This is in fact one of the main tasks which Hibernate does for you.

Another situation would be, if you want Hibernate to tell WHICH attributes are dirty. THEN you would have to write your an interceptor by extending
Code:
EmptyInterceptor
and overwriting the method
Code:
onFlushDirty()
.

Carlo


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 28, 2008 5:25 am 
Newbie

Joined: Tue Dec 04, 2007 10:20 am
Posts: 13
Thank you very much Carlo. The second option would be great but I have a question. How do I let Hibernate do the job of finding out if your object is dirty? Has it got any method or does it check if it's dirty automatically in every update?

Thanks again


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 28, 2008 5:43 am 
Pro
Pro

Joined: Tue Jun 12, 2007 4:13 am
Posts: 209
Location: Berlin, Germany
afertel wrote:
How do I let Hibernate do the job of finding out if your object is dirty? Has it got any method or does it check if it's dirty automatically in every update?


Hibernate does it automatically and transparently for you - it is one of it's main features.

The only time you are involved is if you want to get informed of the changes on attributes Hibernate detects. Then you can use the Interceptor mechanism.

Carlo
--------
if this posts helped, please give me some credits.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 28, 2008 5:46 am 
Newbie

Joined: Tue Dec 04, 2007 10:20 am
Posts: 13
Ok, so if I just want not to update an object if it's not dirty Hibernate will do that automatically without the needing of adding anything to the mapping files, isn't it?

Great, I didn't know this feature. Thank you very much, I'll give you credits. Thanks again


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 28, 2008 5:50 am 
Newbie

Joined: Tue Dec 04, 2007 10:20 am
Posts: 13
Ok, it does automatically. But I want to know if an object is dirty just to add a history record. For that I suppose that I have to develop an interceptor, but when I call it, do I have to set all the arguments

Code:
findDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types)


whenever I call this method or does Hibernate have any method to know the property names, the previous state and the types by itself?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 28, 2008 7:29 am 
Pro
Pro

Joined: Tue Jun 12, 2007 4:13 am
Posts: 209
Location: Berlin, Germany
afertel wrote:
Ok, it does automatically. But I want to know if an object is dirty just to add a history record. For that I suppose that I have to develop an interceptor, but when I call it, do I have to set all the arguments

Code:
findDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types)


whenever I call this method or does Hibernate have any method to know the property names, the previous state and the types by itself?


Yes, for history purposes you have to implement an interceptor. But be aware: you must not use the Hibernate session in this interceptor (if you need a session method, for instance to save a history record, you must use another session); and: your interceptor must be thread safe and should not throw. If you are using JPA, then your interceptor must be a stateless class and you have no access to EntityManager.

That said, I show you how I made a history interceptor. It's interesting part is this:
Code:
public class HistoryInterceptor extends EmptyInterceptor {

  private static Logger logger = LoggerFactory.getLogger(HistoryInterceptor.class);
 
  /**
   * Called when an object is detected to be dirty, during a flush. The interceptor may modify the detected
   * <tt>currentState</tt>, which will be propagated to both the database and the persistent object.
   * Note that not all flushes end in actual synchronization with the database, in which case the
   * new <tt>currentState</tt> will be propagated to the object, but not necessarily (immediately) to
   * the database. It is strongly recommended that the interceptor <b>not</b> modify the <tt>previousState</tt>.
   *
   * @return <tt>true</tt> if the user modified the <tt>currentState</tt> in any way.
   */
  @Override
  public boolean onFlushDirty(final Object pEntity,
                              final Serializable pId,
                              final Object[] pCurrentState,
                              final Object[] pPreviousState,
                              final String[] pPropertyNames,
                              final Type[] pTypes) throws CallbackException {
    // there must no exception be uncaught here!
    try {
.....

Finally, I don't think you should call into the
Code:
findDirty
method.

Carlo
-------------------------
please give me some credits if this post helped you


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 28, 2008 8:05 am 
Newbie

Joined: Tue Dec 04, 2007 10:20 am
Posts: 13
Ok, I've created the interceptor and started a session

Code:
GetDirtyStatus interceptor=new GetDirtyStatus();
      Session session=this.getSessionFactory().openSession(interceptor);


I want the interceptor class to return true or false whether the object is dirty or not, so I just have to implement the onSave method haven't I?

When I do that I've debugged to see what has happened, the value of the new object, but I can't see what was the value of that object before the update. Do you know what method should I use?

Thanks a million again


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 28, 2008 2:43 pm 
Pro
Pro

Joined: Tue Jun 12, 2007 4:13 am
Posts: 209
Location: Berlin, Germany
afertel wrote:

I want the interceptor class to return true or false whether the object is dirty or not, so I just have to implement the onSave method haven't I?


I still hold that you can use
Code:
onFlushDirty
in your interceptor. You get the dirty object und you get old and the new values for the attributes (in the object arrays for previous and currentState). The corresponding propertyNames tell you the attributes names.

So you might create within this method a history entity object - but you would have to use a second, temporary session within this method.

(In my project I used a Timer EJB, which I gave the history records to save them in a separate transaction, when the timer called the bean).

Carlo


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 29, 2008 5:51 am 
Newbie

Joined: Tue Dec 04, 2007 10:20 am
Posts: 13
Ok, I'm trying to do it with the onFlushDirty but this method is not called when I call the save method. Do I have to call another method in the session in order to get to onFlushDirty method on the interceptor??

I've got another problem, which is

Illegal attempt to associate a collection with two open sessions

But I just open one session

Thank you very much helping me with this feature of Hibernate


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 29, 2008 6:39 am 
Pro
Pro

Joined: Tue Jun 12, 2007 4:13 am
Posts: 209
Location: Berlin, Germany
afertel wrote:
Ok, I'm trying to do it with the onFlushDirty but this method is not called when I call the save method. Do I have to call another method in the session in order to get to onFlushDirty method on the interceptor??

No, you don't have to. You just have to register the interceptor (getSessionFactory().openSession(interceptor). Hibernate will call it when it tries to flush dirty objects.

Quote:
I've got another problem, which is Illegal attempt to associate a collection with two open sessions. But I just open one session

Take this error message as it is. There must exist a second session, which you might have forgotten to close.

Carlo
--------------------------------
if this post helped you please give me credits.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 01, 2008 6:13 am 
Newbie

Joined: Tue Dec 04, 2007 10:20 am
Posts: 13
Thank you very much, you've been very helpful. It works as I wanted now, so another credit for you. Thanks again


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 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.