-->
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.  [ 11 posts ] 
Author Message
 Post subject: Interceptor onFlushDirty()
PostPosted: Thu Mar 24, 2005 6:38 pm 
Newbie

Joined: Mon Oct 04, 2004 7:13 am
Posts: 19
Hibernate version: 2.1.7

Mapping documents:
<class name="com.test.Fred" table="Fred">

<id name="id" unsaved-value="null" >
<column name="FredID" not-null="true"/>
<generator class="assigned"/>
</id>

<property name="name" column="FredName" />


</class>


Code:

/////////////////////////////////////////////////////////////////////
Session session = sessionFactory.openSession(conn, new TestInterceptor());

Transaction tx = session.beginTransaction();

Fred fred = (Fred) session.load(Fred.class, new Integer(1));

fred.setName("John");

//Each call to getNamedQuery forces a flush()!!!
Query query = session.getNamedQuery("selectAgreedTrips");
query.list();

tx.commit();
session.close();
////////////////////////////////////////////////////////////////////

class TestInterceptor implements Interceptor {


public boolean onFlushDirty(Object obj, Serializable id, Object[] newValues,
Object[] oldValues, String[] properties, Type[] types)
throws CallbackException {

System.out.println("onFlushDirty old:" + oldValues + " new:" + newValues);


return false;
}
.....
/////////////////////////////////////////////////////////////////


In the above code, the onFlushDirty method is invoked twice. I think this is wrong. It should only be invoked once.
The namedQuery is forcing a flush, as well as the commit().


This is a real problem for me. I use the Interceptor to create audit trails. But I find I am generating multiple identical records because of the above problem.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 27, 2005 5:14 am 
Newbie

Joined: Mon Oct 04, 2004 7:13 am
Posts: 19
I guess this must be a bug then. Should I riase it in JIRA as such?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 27, 2005 6:14 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
as you dont show what actually happens then i cant consider it a bug since flush occurs multiple times.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 29, 2005 7:13 am 
Newbie

Joined: Mon Oct 04, 2004 7:13 am
Posts: 19
Here is the output I get:

onFlushDirty old:Bill new:John
onFlushDirty old:Bill new:John

Note that the onFlushDirty() method is triggered twice. Once for the commit, but before that if gets triggered once for each call to query.list().

Here's the problem:

query.list() calls
session.findBySQL() which calls
session.autoFlushIfRequired().

autoFlushIfRequired() then calls flushEverything() which triggers the interceptor. However, execute() is never invoked because areTablesToBeUpdated() returns false. So the interceptor is triggered even though the data has not been flushed to the database.

Looking through the hibernate code, I can see that you might need to flush on a call to findBySQL(). This ensures the integrity of the data you read, though you only need to truly flush if the query is reading from a table that you have already updated in the current session - hence the call to areTablesToBeUpdated(). But why is the call to flushEverything() outside the if clause? ie why not do:


Code:
   private boolean autoFlushIfRequired(Set querySpaces) throws HibernateException {

      if ( flushMode==FlushMode.AUTO && dontFlushFromFind==0 ) {

         int oldSize = collectionRemovals.size();

         //flushEverything();

         if ( areTablesToBeUpdated(querySpaces) ) {

            log.trace("Need to execute flush");
flushEverything();
            execute();
            postFlush();
            // note: execute() clears all collectionXxxxtion collections
            return true;
         }
         else {....





To work around the problem I need to manually insert calls to session.flush() immediately prior to every query.list(). I could probably also do something with FlushMode.

I hope this proviced enough detail.

thanks,
Mike


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 29, 2005 7:56 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
yes i see your point.

does use of <synchronize> in the native sql works ? (you need named queries for this)

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 29, 2005 8:25 am 
Newbie

Joined: Mon Oct 04, 2004 7:13 am
Posts: 19
I don't understand what you mean by <synchronized>. I couldn't find any mention of it in the doc.

To work around I have the choice of either doing a flush prior to each findBySQL() - which ensures consistent data but has an overhead. Or using FlushMode.COMMIT (or NEVER) and run a small risk of stale data. I'm opting for the latter option.

However, I still think this is a minor bug in the hibernate code.

thanks,
Mike


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 29, 2005 8:34 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 6:10 am
Posts: 8615
Location: Neuchatel, Switzerland (Danish)
well its on our doc todo list:

Code:
<sql-query name="organizationCurrentEmployments">
    <return alias="emp" class="Employment"/>
    <synchronize table="EMPLOYMENT"/>
    SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer},
        STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},
        REGIONCODE as {emp.regionCode}, ID AS {emp.id}
    FROM EMPLOYMENT
    WHERE EMPLOYER = :id AND ENDDATE IS NULL
    ORDER BY STARTDATE ASC
</sql-query>


see that this query tells hibernate via <synchronize> what tables the data comes from.

try to see if adding that helps with your flushing problem.

if not, i would ask you to make a bug report on it with a simple failing test case.

_________________
Max
Don't forget to rate


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 30, 2005 5:29 am 
Newbie

Joined: Mon Oct 04, 2004 7:13 am
Posts: 19
Thanks for your help max, but the <synchronize> made no difference. I'll raise a bug and create a failing test as you asked.


Top
 Profile  
 
 Post subject: Multiple calls to OnFlushDirty
PostPosted: Mon Feb 26, 2007 8:10 pm 
Newbie

Joined: Wed Jun 22, 2005 12:28 pm
Posts: 2
I am running into the same issue and was wondering if there was a resolution found other than changing flush mode to commit.

I have read something about similar issues arrising due to a bad hashcode and was wondering if anyone could confirm and perhaps expand upon this issue.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 23, 2008 10:35 am 
Beginner
Beginner

Joined: Wed May 23, 2007 1:07 pm
Posts: 28
dovoto, what do you mean bad hashcode? In which class?


I also have the same issue. For now I've switched to FlushMode.COMMIT, but was wondering if any of the other posters has managed to find other solutions for this problem.


Top
 Profile  
 
 Post subject: Re: Interceptor onFlushDirty()
PostPosted: Tue Jul 19, 2011 9:04 am 
Newbie

Joined: Tue Apr 26, 2011 4:47 am
Posts: 4
Hi,

We also have the same problem in our project.
We listen to onFlushDirty calls and perform additional operations like audit and validation based on previouse and current state.
We work in ATO flush mode (default).
The problem is when AUTO flush is called before query execution, Interceptor.onFlushDirty() is called, but hibernate doesn't flsuh anything to DB.
Then again if another query is executed, onFlushDirty is called again with the SAME previous state as before, and so on.

I saw a bug was reported for this - see below, but was closed with 'as designed' explanation:
https://hibernate.onjira.com/browse/HB-1480

Why is this behavior expected? What is the solution to only be notified before actual flush?
I saw it was suggested to use flsuh mode COMMIT, but I'n not sure what are the implrcations and ihow can I be sure stale data won't be returned from queries in such case.

Thanks.


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