-->
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.  [ 7 posts ] 
Author Message
 Post subject: Session/Criteria mystery has me stumped
PostPosted: Mon Jan 16, 2006 6:15 pm 
Beginner
Beginner

Joined: Wed Nov 30, 2005 4:58 pm
Posts: 22
Location: Austin, TX
My problem: A criteria gets me an object. I delete it and add another. Later I run the same criteria and it retreives the object I thought I deleted earlier. Further, the criteria does not return the added object even though it would qualify for the results. All code uses the same session object and as far as I can tell the transaction has remained open throughout these operations.

I think the session should remember that I deleted the object and should not return it in the results of any future criteria built from that session. Further, it should return the newly added object, since it qualifies.

When the transaction commits I get erroneous results because of what the criteria saw in the seesion. For example consider the following actions on WidgetCache objects.

pk=45 (pre-exists in DB at session start)
delete pk=45
insert pk=70
delete pk=45* (incorrect, criteria should have found and deleted pk=70)
insert pk= 90

After the transaction commits, the table contains both pk=70 and pk=90. I want it to contain only pk=90. If the criteria returned the correct results, all would be fine, I think.

So, maybe I'm abusing the session, or have got something misconfigured, but after spending a couple of hours reading the docs and poking around this app (which I did not write, but must maintain) I cannot find an explanation for the behavior. The configuration object is pretty standard and does not have a lot of customizations.

If anyone has some ideas, I'd love to hear them.

Here is the simplified (although not much) code for the criteria, delete, and insert.

Code:
public void updateWidgetCache (Session session Widget theWidget) {
  Criteria crit = session.createCriteria (WidgetCache.class);
  crit.add (<some_expression> );
  List currentIssueList = crit.list ();
  WidgetCache wc = getWidgetInCache(currentIssueList , theWidget);
  if (wc ! null) {
    session.delete(wc);
    WidgetCache.create(session, theWidget);
  } else {
    WidgetCache.create(session, theWidget);
  }
}

[in WidgetCache.java]
public WidgetCache create (Session session, Widget theWidget) {
  WidgetCache wc = new WidgetCache();
  copySomeAttributes(theWidget, wc);
  session.save(wc);
  return wc;
}

Our sessions are obtained from the factory like this:

Session session = factory.openSession();
session.setFlushMode(FlushMode.COMMIT);
return session;


Here is how the Configuration object is set up:

Configuration cfg = new Configuration();
cfg.setProperty("hibernate.connection.driver_class", driver);
cfg.setProperty("hibernate.connection.url", url);
cfg.setProperty("hibernate.connection.username", username);
cfg.setProperty("hibernate.connection.password", password);
cfg.setProperty("hibernate.c3p0.min_size", "5");
cfg.setProperty("hibernate.c3p0.max_size", "20");
cfg.setProperty("hibernate.c3p0.timeout", "1800");
cfg.setProperty("hibernate.c3p0.max_statements", "50");
cfg.setProperty("hibernate.dialect", dialect);
cfg.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.HashtableCacheProvider");
        cfg.addResource("app.hbm.xml");
factory = cfg.buildSessionFactory();




Hibernate version: 3.0.2
Name and version of the database you are using: MySQL 4.1.12


Top
 Profile  
 
 Post subject: Re: Session/Criteria mystery has me stumped
PostPosted: Tue Jan 17, 2006 12:02 am 
Regular
Regular

Joined: Tue Dec 14, 2004 5:21 am
Posts: 104
Location: india
bchamp wrote:
pk=45 (pre-exists in DB at session start)
delete pk=45
insert pk=70
delete pk=45* (incorrect, criteria should have found and deleted pk=70)
insert pk= 90
After the transaction commits, the table contains both pk=70 and pk=90. I want it to contain only pk=90. If the criteria returned the correct results, all would be fine, I think.



how could it be 90 only . you arent touching 70

_________________
sHeRiN
thanks for your ratings ...... :)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 17, 2006 12:25 am 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
You have explicitly set the FlushMode to COMMIT, so nothing in your write cache is going to the DB until you commit. Therefore, any selects done will not notice any updates/inserts/deletes, because you haven't committed them. Either remove the change of FlushMode, or explicitly commit the transaction before each select.

Best practice for transactions suggests that you should not leave a transaction open for any longer than absolutely necessary. This includes for selects. You should do all your selects, start your transaction, do all your updates, then commit your transaction. In your example, you don't want a transaction at all: you want "auto-commit" functionality, which is configured by setting your FlushMode to ALWAYS. I don't recommend doing that (it's very inefficient), but if you're going to do selects inside transactions, it is your safest bet.


Top
 Profile  
 
 Post subject: Re: Session/Criteria mystery has me stumped
PostPosted: Tue Jan 17, 2006 2:09 pm 
Beginner
Beginner

Joined: Wed Nov 30, 2005 4:58 pm
Posts: 22
Location: Austin, TX
zzyborg wrote:
bchamp wrote:
pk=45 (pre-exists in DB at session start)
delete pk=45
insert pk=70
delete pk=45* (incorrect, criteria should have found and deleted pk=70)
insert pk= 90
After the transaction commits, the table contains both pk=70 and pk=90. I want it to contain only pk=90. If the criteria returned the correct results, all would be fine, I think.



how could it be 90 only . you arent touching 70


It would be 90 only if the criteria had returned 70 instead of 45. The criteria seems unaware that 45 has been deleted. Perhaps I should have written it like this:

pk=45 (pre-exists in DB at session start)
criteria returns 45
delete pk=45
insert pk=70
criteria returns 45 (when I want it to return 70)
delete pk=45* (incorrect, criteria should have found and deleted pk=70)
insert pk= 90

Sorry I wasn't clear.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 17, 2006 2:12 pm 
Beginner
Beginner

Joined: Wed Nov 30, 2005 4:58 pm
Posts: 22
Location: Austin, TX
Quote:
You have explicitly set the FlushMode to COMMIT, so nothing in your write cache is going to the DB until you commit. Therefore, any selects done will not notice any updates/inserts/deletes, because you haven't committed them. Either remove the change of FlushMode, or explicitly commit the transaction before each select.


Hmmm, sounds promising. So I made a change like this:


Code:
public void updateWidgetCache (Session session Widget theWidget) {
  Session innerSession = sessionFactory.openSession();
  Transaction tx = innerSession.beginTransaction();
  try {
    Criteria crit = session.createCriteria (WidgetCache.class);
    crit.add (<some_expression> );
    List currentIssueList = crit.list ();
    WidgetCache wc = getWidgetInCache(currentIssueList , theWidget);
    if (wc ! null) {
      session.delete(wc);
      WidgetCache.create(session, theWidget);
    } else {
      WidgetCache.create(session, theWidget);
    }
    tx.commit();
  } catch (HibernateException he) {
    tx.rollback();
  }
}


As you can see, I am using a new session and transaction object. However, the criteria object still sees deleted rows.

Wow, I must really misunderstand how sessions and transactions work.

Next I will try it without the FlushMode.COMMIT and without an innerSession.

Thanks for your insight. If you have any more, please share them. I'm learning a lot.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 17, 2006 2:37 pm 
Beginner
Beginner

Joined: Wed Nov 30, 2005 4:58 pm
Posts: 22
Location: Austin, TX
Success!! Changing the FlushMode from COMMIT back to its default of AUTO gives the desired results. So, this is how I will fix the bug.

However, I'm still puzzled that creating a whole new session as shown in my last post did not work. If anyone knows why, please tell me so I can understand better how sessions and transactions work.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 17, 2006 4:55 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
I would guess that the reason it didn't work with two sessions is because your outer session never went back to the DB, for efficiency's sake. You would need to evict the objects from the outer session so that it knows to do a fresh select.

However, don't use two sessions from one thread like that: if one session tries to read from or write to a table that the other session has a lock on (because its transaction hasn't been committed or rolled back), then you'll be deadlocked. Use one session per thread. Specifically, use one short-lived session and shorter transactions per thread.


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