[hibernate-issues] [Hibernate-JIRA] Closed: (HHH-1578) queries inside events - scenario which fails + fix

Steve Ebersole (JIRA) noreply at atlassian.com
Mon Mar 21 13:01:05 EDT 2011


     [ http://opensource.atlassian.com/projects/hibernate/browse/HHH-1578?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Steve Ebersole closed HHH-1578.
-------------------------------


Closing stale resolved issues

> queries inside events - scenario which fails + fix 
> ---------------------------------------------------
>
>                 Key: HHH-1578
>                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1578
>             Project: Hibernate Core
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 3.1.2
>            Reporter: Tomasz Bech
>            Assignee: Steve Ebersole
>
>  It is related to the forum topic: http://forum.hibernate.org/viewtopic.php?p=2294885#2294885. However I put full and better description below.
> preInsert event is used to make query on DB - to check some integrity.
> Following scenario fails:
> - insert object A;
> - insert object A'; (of type A, but different values than before)
> - commit;
> it gives stack trace:
> This gives exception:
> aused by: org.hibernate.exception.GenericJDBCException: could not insert:
> 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.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2078)
> at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2427)
> at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:51)
> at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:243)
> at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:227)
> at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
> at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296)
> at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
> at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1009)
> at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:356)
> at org.hibernate.transaction.CacheSynchronization.beforeCompletion(CacheSynchronization.java:59)
> at org.jboss.tm.TransactionImpl.doBeforeCompletion(TransactionImpl.java:1473)
> at org.jboss.tm.TransactionImpl.beforePrepare(TransactionImpl.java:1092)
> at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:306)
> ... 63 more
> Caused by: java.sql.SQLException: Connection handle has been closed and is unusable
> at org.jboss.resource.adapter.jdbc.WrappedConnection.checkStatus(WrappedConnection.java:526)
> at org.jboss.resource.adapter.jdbc.WrappedConnection.checkTransaction(WrappedConnection.java:513)
> at org.jboss.resource.adapter.jdbc.WrappedStatement.checkTransaction(WrappedStatement.java:537)
> at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:223)
> at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:23)
> at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2062)
> ... 76 more
> Following scenario works fine:
> - insert object A
> - commit;
> Following scenario also works fine:
> - insert object A
> - insert object B
> - commit;
> I've spend a day to analyze the problem, as the preInsert+queries are crucial for our project.
> The order of operations is as follows:
> - prepareBatchStatement is called on AbstractBatcher;
> - my suplied query is executed;
> - prepareBatchStatement is called on AbstractBatcher;
> The problem appears because the 'batchUpdate' statement is reused in second call:
> public PreparedStatement prepareBatchStatement(String sql)
> throws SQLException, HibernateException {
> sql = getSQL( sql );
> if ( !sql.equals(batchUpdateSQL) ) {
> batchUpdate=prepareStatement(sql); // calls executeBatch()
> batchUpdateSQL=sql;
> }
> else {
> log.debug("reusing prepared statement"); //here - REUSING prepare statement
> log(sql);
> }
> return batchUpdate;
> }
> and it is why insert A, preinsert-query, insert B scenario works, and insert A, preinsert-query, query A' doesn't.
> The query which was called just before the second insert of A' has closed its connection, but this connection belongs to batchUpdate too :(.
> The function responsible for tracking if the connection cen be closed is:
> public boolean hasOpenResources() {
> return resultSetsToClose.size() > 0 || statementsToClose.size() > 0 ;
> }
> It simply doesn't take into consideration that batchUpdate also has open connection - batchUpdate is not added to the statementsToClose also (as it is in the prepareQueryStatement).
> Golden patch would be to add batchUpdate to the statementsToClose map.
> But the same can be reach by (this is a fix):
> public boolean hasOpenResources() {
> return resultSetsToClose.size() > 0
>     || statementsToClose.size() > 0
>     || batchUpdate != null;
> }
> BatchUpdate when executed (in executeBatch) is closed and set to null = its connection can be released.
> I've tested the change, there is no side-effects (no leaked open connections) and the above scenario works.
> (in fact full execution order is: preInsert-query, insert A, preInsert--query, insert A', but the first preInsert-query works ok.)

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list