-->
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.  [ 14 posts ] 
Author Message
 Post subject: Hibernate 3.1rc1: autoClose session in commit
PostPosted: Mon Oct 10, 2005 8:26 am 
Pro
Pro

Joined: Mon Jan 24, 2005 5:39 am
Posts: 216
Location: Germany
I have some problems with the changed commit behavior in
Hibernate 3.1 rc1. I already read http://www.hibernate.org/42.html
and I think its much easier for most applications.
However one of our benchmarks now needs 4x more
time.

We are using the a session-per-conversation pattern.
With hibernate.current_session_context_class="thread".
Thus our session is closed on each commit !
That very different from the behavior in hibernate <= 3.1 b3.

It looks like I can alter this behaviour using my own
implementation of CurrentSessionContext. I didnt try this
so far.

Our benchmark worked like this using a stateful session:

Code:
Transaction tx = session.beginTransaction();
Query q = session.createQuery(<someQuery>);
ScrollableResults users = q.scroll();
int cnt = 0;
while( users.next() ) {
   User user = (User) users.get(0);
   user.updateUser();
   if (++cnt % objectsPerTA == 0) {
      session.flush();
      tx.commit();
      session.clear();
      tx.begin();
   }            
}


In 3.1rc1 after commit the session is closed and tx.begin() does not work anymore. Opening a new session doesnt work either, since the cursor query is connected to the old session and is broken too.
Creating two sessions one for read and one for write gives a concurrent
data access exception on large numbers of objects.
Committing just once at the end of the loop works but is four times slower.

So an implementation of CurrentSessionContext will probably solve this problem. And certainly a stateless session would be the best solution.
Perhaps someone else has similar problems.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 10, 2005 8:42 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
You are not using a single session-per-request with a single database transaction. Hence, you should not use the current_session_context_class="thread", which gives you a 1:1 session/transaction model. Don't use getCurrentSession(), in other words, if it doesn't do what you want to do. Of course you can customize it, instead if writing session/transaction handling completely from scratch, like you had to do before anyway.

"Committing just once at the end of the loop works but is four times slower."

So you base your transactions success on performance instead of atomic use cases?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 10, 2005 9:37 am 
Pro
Pro

Joined: Mon Jan 24, 2005 5:39 am
Posts: 216
Location: Germany
Thanks Christian,

you are certainly right and as I said:
the new behavior is really much easier.
Its just quiet different from the old one.
So what do I have to do to get the old behavior?

e.g. set
Code:
hibernate.current_session_context_class=MySessionContextClass


MySessionContextClass is a subclass of ThreadLocalSessionContext
and overwrite the following methods like:

Code:
protected boolean isAutoCloseEnabled() {
   return false;
}
protected boolean isAutoFlushEnabled() {
   return false;
}
protected ConnectionReleaseMode getConnectionReleaseMode() {
   return ConnectionReleaseMode.ON_CLOSE;
}


Will this do?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 10, 2005 10:46 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
To get the old behavior you have to not use the new feature, simple as that. Don't use getCurrentSession() or implement your own CurrentSessionContext if the built-in implementations don't do what you want.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 10, 2005 11:06 am 
Pro
Pro

Joined: Mon Jan 24, 2005 5:39 am
Posts: 216
Location: Germany
Sorry to bother you, perhaps I am just too blind.
In previous versions of hibernate I used

Code:
sessionFactory.openSession();


and after session.commit()
the session was still open, i.e.

Code:
session.beginTransaction()


still worked.
But in Hibernate 3.1 rc1 my session is closed
after commit. Is there another way of obtaining
a "reusable" session, i.e. a session with which I
can do several commits?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 10, 2005 11:20 am 
Newbie

Joined: Mon Oct 10, 2005 4:49 am
Posts: 5
Hello,

I'm not sure you are involved with that, but there is a property
<b>hibernate.transaction.auto_close_session</b> that tells hibernate to auto close the session after the commit.
As you did not put your hibernate config file, could you check if you are using that property and that this one is not true.

I hope it helps. (Sorry but i'm using v3.0.3)

Jim


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 10, 2005 11:28 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Quote:
But in Hibernate 3.1 rc1 my session is closed
after commit.


This should only ever happen if you configured current_session_context_class to "thread" or "jta", or if you are using a TransactionManagerLookup (mandatory JTA) and getCurrentSession().

Of course the same happens if you enabled transaction.auto_close_session and the traditional openSession()/commit().


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 10, 2005 11:37 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
The easiest approach, I think would be a custom CurrentSessionContext impl derived from ThreadLocalSessionContext. Specifically, override ThreadLocalSessionContext.isAutoCloseEnabled().

The downfall of this approach is that you'd need to manage actual closing of the session yourself at "some point".


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 10:41 am 
Pro
Pro

Joined: Mon Jan 24, 2005 5:39 am
Posts: 216
Location: Germany
many thanks.
You are partially right and my knowledge of hibernate is growing, but even if I take everything into account,
I still have a different behaviour between h3.1rc1 and h3.1b3.
I found the reason in the method afterTransactionCompletion
of class SessionImpl.

Here is the code of h3.1b3:

Code:
   public void afterTransactionCompletion(boolean success, Transaction tx) {
      log.trace( "after transaction completion" );

      persistenceContext.afterTransactionCompletion();
      actionQueue.afterTransactionCompletion(success);

      if ( isRootSession && tx!=null ) {

         try {
            interceptor.afterTransactionCompletion(tx);
         }
         catch (Throwable t) {
            log.error("exception in interceptor beforeTransactionCompletion()", t);
         }
         
      }
      
      if (autoClear) clear();

   }


and here is h3.1rc1:

Code:
   public void afterTransactionCompletion(boolean success, Transaction tx) {
      log.trace( "after transaction completion" );

      persistenceContext.afterTransactionCompletion();
      actionQueue.afterTransactionCompletion(success);

      if ( isRootSession && tx!=null ) {

         try {
            interceptor.afterTransactionCompletion(tx);
         }
         catch (Throwable t) {
            log.error("exception in interceptor beforeTransactionCompletion()", t);
         }
         disconnect();
      }
      
      if (autoClear) clear();
   }


The problem is the newly added disconnect method.

Here is my hibernate.config.xml:

Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
   "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
   "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

    <session-factory>
        <property name="dialect">org.hibernate.dialect.DB2Dialect</property>
        <property name="hibernate.default_schema">dbo</property>
        <property name="connection.driver_class">COM.ibm.db2.jdbc.app.DB2Driver</property>
        <property name="connection.username">ifb</property>
        <property name="connection.password">kennwort</property>
        <property name="connection.url">jdbc:db2:dbtest</property>
        <property name="jdbc.batch_size">20</property>
        <property name="show_sql">false</property>
        <property name="hibernate.cache.use_second_level_cache">false</property>

      <property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
      <property name="c3p0.acquire_increment">1</property>
      <property name="c3p0.idle_test_period">100</property>
      <property name="c3p0.max_size">100</property>
      <property name="c3p0.max_statements">100</property>
      <property name="c3p0.min_size">1</property>
      <property name="c3p0.timeout">100</property>
      
        <!-- Mapping files -->
        <mapping resource="com/ifbag/okular/base/hibernate/tst/User.hbm.xml"/>

    </session-factory>

</hibernate-configuration>


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 11:42 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
Ah yes, did not look at the code. I was just replying to the later statements.

You'd need to change the "tx.begin()" call in the middle of that loop to "tx = session.beginTransaction()".

In the next release (will not work with rc1) you would also be able to do:
session.getTransaction().commit();
session.clear();
session.getTransaction().start();


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 11, 2005 11:39 pm 
Newbie

Joined: Wed Jan 26, 2005 10:51 pm
Posts: 3
Location: Taiwan
I too have the multiple-transaction-per-session problem after switched to 3.1 rc1. I manage sessions by myself and not to use getCurrentSession() and other new features like current_session_context_class. With 3.1 rc1, once the transaction is committed, operations such as session.createQuery() failed and the exception says "Not able to obtain connection", After reading hibernate source code, I put connection.release_mode=after_transaction into my hibernate.cfg.xml so that I can continue using session to createQuery() and start another transaction. This just makes part of my application work with 3.1 rc1. Another problem I have is committing a transaction would also close the iterator returned by session.createQuery().iterate(), I am still trying to read source code to solve this.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 12, 2005 2:49 am 
Pro
Pro

Joined: Mon Jan 24, 2005 5:39 am
Posts: 216
Location: Germany
Thanks Steve,

Code:
session.beginTransaction()


solves some of my problems. And
hibernate.connection.release_mode is default on_close
which seems to be ok. The problem I still have is that
my cursor queries are broken after commit.
This following code was ok in hib3.1b3:

Code:
Session session = hsession.getSession();
Transaction tx = session.beginTransaction();
Query q = session.createQuery(<someQuery>);
ScrollableResults scroll = q.scroll();
int cnt = 0;
while( scroll.next() ) {
   User user = (User) scroll.get(0);
   user.updateUser();
   if (++cnt % objectsPerTA == 0) {
      //flush a batch of updates and release memory:
      session.flush();
      tx.commit();
      session.clear();
      tx = session.beginTransaction();
   }            
}


Now I get this stacktrace:

Code:
WARN  - SQL Error: 0, SQLState: null
ERROR - You can't operate on a closed ResultSet!!!
org.hibernate.exception.GenericJDBCException: could not advance using next()
   at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:91)
   at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:79)
   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
   at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:29)
   at org.hibernate.impl.ScrollableResultsImpl.next(ScrollableResultsImpl.java:104)
   at com.ifbag.okular.base.hibernate.tst.HibBatch.updateCursor(HibBatch.java:248)
   at com.ifbag.okular.base.hibernate.tst.HibBatch.start(HibBatch.java:98)
   at com.ifbag.okular.base.hibernate.tst.HibBatch.main(HibBatch.java:56)
Caused by: java.sql.SQLException: You can't operate on a closed ResultSet!!!
   at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:104)
   at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:65)
   at com.mchange.v2.c3p0.impl.NewProxyResultSet.next(NewProxyResultSet.java:3047)
   at org.hibernate.impl.ScrollableResultsImpl.next(ScrollableResultsImpl.java:99)
   ... 3 more
Caused by: java.lang.NullPointerException
   at com.mchange.v2.c3p0.impl.NewProxyResultSet.next(NewProxyResultSet.java:3041)
   ... 4 more


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 18, 2005 5:02 am 
Pro
Pro

Joined: Mon Jan 24, 2005 5:39 am
Posts: 216
Location: Germany
Since hibernate 3.1 rc2 the stateless session has the same problem:
cursors (ScrollableResults) are broken after commit.
However setting:
Code:
<property name="hibernate.connection.release_mode">on_close</property>


solves the problem.

You can find more info about this in JIRA issue: HHH-1038


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 18, 2005 7:46 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
Holding cursors open across db transaction boundaries is dubious. A lot of databases won't even let you do that.


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