-->
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.  [ 5 posts ] 
Author Message
 Post subject: Multiple transactions that insert into same table
PostPosted: Wed Dec 05, 2007 6:13 pm 
Beginner
Beginner

Joined: Wed Aug 27, 2003 3:54 am
Posts: 28
In one of our applications we are facing a problem when multiple transactions insert rows into the same table. We are using Hibernate with Spring.

We have a table that contains the list of client numbers. Our application creates additional client information that should be linked to the client number. In a normal situation, the processing checks the existence of the client number in the table. If it exists, it is referenced. If it does not exist, it is inserted into the table. A unique constraint has been defined on the client numbers.

The problem occurs when multiple transactions are performing this checking mechanism. When 2 transactions (T1 and T2) are launched in parallel, T1 performs the check on client number CN1. Since this client number does not exist, T1 inserts it. A couple of ms after T1 performed the check, T2 performs the same check. Since T1 has not yet been committed, CN1 does not exist for T2. As a result, CN1 is inserted by T2. T1 commits and everything is OK. T2 commits, but the unique constraint is violated and Hibernate generates an Exception. Which is just fine.

In this case, I would like to recover the client number that has been generated and which is available in the database. Once I have this client number (and its technical id), I can attach it to the client information I wanted to insert in T2.

Is this possible with Hibernate ? If yes, how ?

Hibernate version:
3.2.5GA
Code between sessionFactory.openSession() and session.close():
Managed by Spring
Name and version of the database you are using:
SQLServer 2005


Top
 Profile  
 
 Post subject: Re: Multiple transactions that insert into same table
PostPosted: Wed Dec 05, 2007 6:47 pm 
Expert
Expert

Joined: Wed Apr 11, 2007 11:39 am
Posts: 735
Location: Montreal, QC
stlecho wrote:
In this case, I would like to recover the client number that has been generated and which is available in the database. Once I have this client number (and its technical id), I can attach it to the client information I wanted to insert in T2.

Is this possible with Hibernate ? If yes, how ?


Why don't you try again on a ConstraintViolationException? A second failure though doesn't look good. In addition, you might want to set your transaction isolation level to READ COMMITED if the first transaction has a chance of failure after inserting the data.

Farzad-


Top
 Profile  
 
 Post subject: Re: Multiple transactions that insert into same table
PostPosted: Thu Dec 06, 2007 4:59 am 
Beginner
Beginner

Joined: Wed Aug 27, 2003 3:54 am
Posts: 28
farzad wrote:
Why don't you try again on a ConstraintViolationException? A second failure though doesn't look good. In addition, you might want to set your transaction isolation level to READ COMMITED if the first transaction has a chance of failure after inserting the data.

Farzad-


When the second transaction T2 is committed, a DataIntegrityViolationException is thrown. In the catch block of this exception, we try to read - officeManager.getByOfficeNr(officeNr) - the value of the client number in the database. Before doing the read, Hibernate automatically flushes the session.

Code:
                if (effectiveOffice == null)
                {
                        // Attempt to create the office entity but recover on duplicate key (concurrent thread).
                        try
                        {
                                // Create the office entity into the database.
                                officeManager.create(candidateOffice);
                        }
                        catch (DataIntegrityViolationException exception)
                        {
                                // Retrieve the office entity created by the concurrent thread.
                                effectiveOffice = officeManager.getByOfficeNr(officeNr);
                        }
                }


When doing the retry Hibernate generates "don't flush the Session after an exception occurs". The stacktrace received when executing effectiveOffice = officeManager.getByOfficeNr(officeNr); is included underneath.

Code:
cause = org.hibernate.AssertionFailure: null id in com.notary.app.invoicing.core.fwk.model.OfficeImpl entry (don't org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:157)
        org.hibernate.AssertionFailure - null id in com.notary.app.invoicing.core.fwk.model.OfficeImpl entry (don't flush the Session after an exception occurs)
        by org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:55)
        StackTrace on org.hibernate.AssertionFailure
                org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:55)
                org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:157)
                org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:113)
                org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:196)
                org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:76)
                org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:35)
                org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:969)
                org.hibernate.impl.SessionImpl.list(SessionImpl.java:1114)
                org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
                org.springframework.orm.hibernate3.HibernateTemplate$29.doInHibernate(HibernateTemplate.java:849)
                org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:372)
                org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:840)
                com.notary.app.invoicing.core.fwk.dao.OfficeDAOImpl.getByOfficeNr(OfficeDAOImpl.java:75)


Is there a way to influence the behavior of autoFlushIfRequired ?

Regards, Stefan Lecho.


Top
 Profile  
 
 Post subject: Re: Multiple transactions that insert into same table
PostPosted: Thu Dec 06, 2007 11:34 am 
Expert
Expert

Joined: Wed Apr 11, 2007 11:39 am
Posts: 735
Location: Montreal, QC
stlecho wrote:
Is there a way to influence the behavior of autoFlushIfRequired ?

Regards, Stefan Lecho.



Hibernate documentation says no Hibernate exception can be treated recoverable. You have to rollback the transaction and close the session. I can also think of many cases in which you can not obtain another session either but give it a try. You might also want to think about putting this unit of work in JMS Queue with a certain number of tries, but this will require you to sit down and redo a part of your design.


Top
 Profile  
 
 Post subject: Re: Multiple transactions that insert into same table
PostPosted: Sun Dec 09, 2007 4:42 pm 
Beginner
Beginner

Joined: Wed Aug 27, 2003 3:54 am
Posts: 28
farzad wrote:
Hibernate documentation says no Hibernate exception can be treated recoverable. You have to rollback the transaction and close the session. I can also think of many cases in which you can not obtain another session either but give it a try. You might also want to think about putting this unit of work in JMS Queue with a certain number of tries, but this will require you to sit down and redo a part of your design.

We are using Hibernate in a Spring-based environment. Re-creating a session is in my opinion not as easy as it seems to be. Can anyone provide an example on how this should be achieved ?

Putting the unit of work is a JMS Queue is a quite heavy solution for a simple problem, i.e. re-reading an already persisted object. I think that Hibernate should provide the developer with a decent solution.


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