You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user-java@ibatis.apache.org by Albert L Sapp <as...@uiuc.edu> on 2007/01/22 19:42:22 UTC
Re: Proper transaction code pattern
We are logging and displaying error reports to the user. Perhaps that
is the wrong approach to take, but I just inherited this as the standard
for coding. None of the try/catch blocks have a finally clause in
them. Instead, they just do a endTransaction in the try part of the
block and also a endTransaction in each of the catches. This seems to
me to be overkill as I would think a finally clause with a
endTransaction should be sufficient whether a exception is being caught
and thrown or the transaction was completed successfully with a commit.
Please forgive my terminology if it is wrong. Even after more than a
year coding Java, I still am not sure what everything is called. I
simply want to make my code as efficient and correct as possible. My
thanks to the list for indulging what is probably a simple question.
Thanks,
Al
Clinton Begin wrote:
> If you call startTransaction() you must guarantee that endTransaction
> is called. The only way to do that is inside a finally block. You
> really should not need a catch block unless you're logging the
> exception or something.
>
> Cheers,
> Clinton
>
> On 1/22/07, Albert L Sapp <as...@uiuc.edu> wrote:
>> Clinton,
>>
>> You mentioned one case where I am unclear what I should be doing. I
>> thought I read the documentation correctly, but still have the
>> question. We use try/catch extensively in our application. All the
>> try/catch are coded with a endTransaction prior to the actual throw of
>> the exception and the results of the endTransaction ignored. Is this
>> really needed? Can't we just have a endTransaction in a finally
>> clause? Am I missing something here? Probably, but I thought I
>> would ask.
>>
>> Sorry, if it is covered in the docs and missed or didn't understand it.
>>
>> Al
>>
>> Clinton Begin wrote:
>> > Hi everyone,
>> >
>> > Reading through the original thread, there is more than one person
>> > confused by sessions and transactions, so here's some clarification.
>> >
>> > There are four levels of control you can have over iBATIS
>> > transactions. They are:
>> >
>> > #1 First is single statement, automatic transaction. In this case,
>> > you execute one statement that gets committed (or rolled back)
>> > automatically by iBATIS. This behaves like JDBC "auto-commit", but it
>> > definitely doesn't use it. iBATIS always explicitly calls
>> > commit/rollback. An example of this single statement approach is:
>> >
>> > sqlMapper.insert("insertPerson",somePerson);
>> >
>> > You don't need a try/finally block or anything. It's all self
>> > contained. This is one transaction.
>> >
>> > #2 The second is multi-statement manual transaction mode. In this
>> > case you have multiple statements you want to succeed or fail as a
>> > group. If one statement fails, they all get rolled back. This is the
>> > most common case for update statements, but can also improve the
>> > performance and consistency of multiple queries in some cases. The
>> > example is:
>> >
>> > try {
>> > sqlMapper.startTransaction();
>> > sqlMapper.insert("insertPerson",somePerson);
>> > sqlMapper.update("updatePerson",someOtherPerson);
>> > sqlMapper.delete("deletePerson",anotherPerson);
>> > sqlMapper.commitTransaction();
>> > } finally {
>> > sqlMapper.endTransaction();
>> > }
>> >
>> > There's no explicit call to rollback(). iBATIS knows if you've called
>> > commit() indicating a successful transaction, otherwise it calls
>> > rollback. This allows you to use try/finally semantics instead of
>> > try/catch (which can get messy). You must ensure that this is always
>> > in a try/finally block as above, otherwise you risk connection leaks.
>> >
>> > #3 The third approach is to manage sessions manually. In the last two
>> > cases sessions were managed automatically. Sometimes you need to do
>> > this for greater control of the broader iBATIS usage scope, but you
>> > might also use it to pass your own connection to iBATIS (openSession()
>> > can take a connection as a parameter). Here's an example:
>> >
>> > SqlMapSession session = sqlMap.openSession()
>> > try {
>> > session.startTransaction()
>> > session.insert("insertPerson",somePerson);
>> > session.update("updatePerson",someOtherPerson);
>> > session.delete("deletePerson",anotherPerson);
>> > session.commitTransaction();
>> > } finally {
>> > try {
>> > session.endTransaction();
>> > } finally {
>> > session.close();
>> > }
>> > // Generally your session scope would be in a wider context and
>> > therefore the
>> > // ugly nested finally block above would not be there. Realize that
>> > sessions
>> > // MUST be closed if explicitly opened (via openSession()).
>> > }
>> >
>> > As you can see, there's definitely more work and more code involved
>> > with managing sessions manually...it's therefore pretty rare. If you
>> > do, you'll usually hide it in some abstract class or perhaps even in a
>> > separate layer of the application. As the comment above says, doing
>> > so will also avoid the need for a nested try/finally block (in C#
>> > using blocks make this a lot cleaner too!).
>> >
>> > #4 Finally, there's 3rd Party session/transaction management. This is
>> > the case if you're using Spring DAO, iBATIS DAO, or some other higher
>> > level persistence framework that has an iBATIS "plug-in". I won't
>> > bother with an example, as you're better off looking them up. The one
>> > we generally recommend is Spring DAO.
>> >
>> > I hope that helps. This is all documented both in the JavaDocs and
>> > the user guide (this is almost a cut and paste from the javadoc). Let
>> > us know if and how we can make it more clear.
>> >
>> > Cheers,
>> > Clinton
>> >
>> > On 1/22/07, Clinton Begin <cl...@gammagarage.com> wrote:
>> >> Cornel,
>> >>
>> >> Richard is right. You're unfortunately mistaken. The following
>> is an
>> >> excerpt from the documentation you responded with:
>> >>
>> >> 'If a connection is in auto-commit mode, then all its SQL statements
>> >> will be executed and committed as individual transactions. Otherwise,
>> >> its SQL statements are grouped into transactions that are terminated
>> >> by a call to either the method commit or the method rollback."
>> >>
>> >> iBATIS always commits or rolls back transactions explicitly with
>> >> commit() and rollback().
>> >>
>> >> Clinton
>> >>
>> >> On 1/22/07, Cornel Antohi <ca...@kepler-rominfo.com> wrote:
>> >> >
>> >> >
>> >> > Hi Richard,
>> >> >
>> >> > I do not agree with you:
>> >> >
>> >>
>> http://java.sun.com/j2se/1.3/docs/api/java/sql/Connection.html#setAutoCommit(boolean)
>>
>> >>
>> >> >
>> >> > Thank you,
>> >> > Cornel
>> >> >
>> >> > ----- Original Message -----
>> >> > From: Yee, Richard K CTR DMDC
>> >> > To: 'user-java@ibatis.apache.org'
>> >> >
>> >> > Sent: Monday, January 22, 2007 6:42 PM
>> >> > Subject: RE: Autocommit not properly handled in Ibatis.
>> >> >
>> >> >
>> >> > Antohi,
>> >> > It looks to me that the code does exactly what Clinton says. If
>> >> autocommit
>> >> > is on, iBATIS turns it off and thus does not use autocommit to
>> commit
>> >> > changes to the DB.
>> >> >
>> >> > -Richard
>> >> >
>> >> >
>> >> >
>> >> > -----Original Message-----
>> >> > From: Cornel Antohi [mailto:cantohi@kepler-rominfo.com]
>> >> > Sent: Monday, January 22, 2007 2:37 AM
>> >> > To: user-java@ibatis.apache.org
>> >> > Subject: Re: Autocommit not properly handled in Ibatis.
>> >> >
>> >> >
>> >> > Hi Clinton,
>> >> >
>> >> > 1) What do you mean by "iBATIS never uses AutoCommit"? Here is what
>> >> I found
>> >> > in:
>> >> >
>> >> > com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransaction
>> >> > --> private void init() throws SQLException, TransactionException
>> >> > // AutoCommit
>> >> > if (connection.getAutoCommit()) {
>> >> > connection.setAutoCommit(false);
>> >> > }
>> >> >
>> >> >
>> >> > Thank you,
>> >> > Cornel
>> >> >
>> >> > ----- Original Message -----
>> >> > From: "Clinton Begin" <cl...@gmail.com>
>> >> > To: <us...@ibatis.apache.org>
>> >> > Sent: Friday, January 19, 2007 8:52 AM
>> >> > Subject: Re: Autocommit not properly handled in Ibatis.
>> >> >
>> >> > A few things:
>> >> >
>> >> > 1) iBATIS never uses AutoCommit.
>> >> >
>> >> > 2) setCommitRequired has nothing to do with AutoCommit. iBATIS
>> uses
>> >> > deferred commits to avoid unecessary commits when no non-queries
>> have
>> >> > been issued. And setCommitRequired is actually parameterized
>> and can
>> >> > be set with <transactionManager ... commitRequired="true">
>> >> >
>> >> > 3) You'll need to post your code so we can see what it's doing.
>> Are
>> >> > you calling startTransaction()? Are you using
>> setUserConnection? Or
>> >> > openSession(conn)?
>> >> >
>> >> > I'm sure with the right information we can resolve this for you
>> >> easily.
>> >> >
>> >> > Clinton
>> >> >
>> >> > On 1/18/07, Yuvraj Shinde <Yu...@sos.sungard.com> wrote:
>> >> > >
>> >> > >
>> >> > >
>> >> > >
>> >> > > Hi all,
>> >> > >
>> >> > >
>> >> > >
>> >> > > I want to know how to handle auto commit in ibatis.if I am
>> >> saving two
>> >> > > records and if I get an exception while saving second record the
>> >> first
>> >> > > record saved should be rolled back.
>> >> > >
>> >> > > But ibatis is saving the first record. How I should handle this
>> >> even
>> >> > > though the auto commit property is explicitly set to false.
>> >> > >
>> >> > >
>> >> > >
>> >> > > Even though AutoCommit value is set to false. Rollback of
>> >> Transaction
>> >> > is
>> >> > > not working.
>> >> > >
>> >> > > I found one Issue in GeneralStatement.java.
>> >> > >
>> >> > > On line 52 request.getSession().setCommitRequired(true);
>> >> > >
>> >> > >
>> >> > >
>> >> > > Here Auto commit is hard coded it should be parameterized so
>> >> that it
>> >> > will
>> >> > > take value from "Auto commit" property of SqlMapConfig.xml.
>> >> > >
>> >> > > Please correct me if I am wrong.please send me a solution.
>> >> > >
>> >> > >
>> >> > >
>> >> > > Regards
>> >> > >
>> >> > > Yuvrajs
>> >> > >
>> >> > >
>> >> > >
>> >> > >
>> >> > >
>> >> > >
>> >> > >
>> >> > >
>> >> > >
>> >> > > Yuvraj Shinde * Senior Software Engineer - Zainet* SunGard *
>> >> Offshore
>> >> > > Services *
>> >> > > Pride Portal,CTS No 103A/5A/1A/1B Bhamburda,Senapati Bapat Road,
>> >> > > shivajinagar,Pune 411016
>> >> > > Tel Direct +91 20 66248045 * Main +91 20 66248000 * Fax +91 20
>> >> 25606222
>> >> > > yuvraj.shinde@sos.sungard.com * www.sungard.com
>> >> > >
>> >> > >
>> >> > >
>> >> > >
>> >> > > Success is never ending and failure is never final.
>> >> > >
>> >> > >
>> >>
>> >
>>
>>
>
Re: Proper transaction code pattern
Posted by Clinton Begin <cl...@gammagarage.com>.
It sounds like you've done a good job recognizing the problem. You're
right that it would be better to put it in the try/finally block,
especially if the code is catching a specific exception (like
SQLException). Think about what happens if an unexpected
RuntimeException is thrown...
You're on the right track.
Cheers, ;-)
Clinton
On 1/22/07, Albert L Sapp <as...@uiuc.edu> wrote:
> We are logging and displaying error reports to the user. Perhaps that
> is the wrong approach to take, but I just inherited this as the standard
> for coding. None of the try/catch blocks have a finally clause in
> them. Instead, they just do a endTransaction in the try part of the
> block and also a endTransaction in each of the catches. This seems to
> me to be overkill as I would think a finally clause with a
> endTransaction should be sufficient whether a exception is being caught
> and thrown or the transaction was completed successfully with a commit.
>
> Please forgive my terminology if it is wrong. Even after more than a
> year coding Java, I still am not sure what everything is called. I
> simply want to make my code as efficient and correct as possible. My
> thanks to the list for indulging what is probably a simple question.
>
> Thanks,
>
> Al
> Clinton Begin wrote:
> > If you call startTransaction() you must guarantee that endTransaction
> > is called. The only way to do that is inside a finally block. You
> > really should not need a catch block unless you're logging the
> > exception or something.
> >
> > Cheers,
> > Clinton
> >
> > On 1/22/07, Albert L Sapp <as...@uiuc.edu> wrote:
> >> Clinton,
> >>
> >> You mentioned one case where I am unclear what I should be doing. I
> >> thought I read the documentation correctly, but still have the
> >> question. We use try/catch extensively in our application. All the
> >> try/catch are coded with a endTransaction prior to the actual throw of
> >> the exception and the results of the endTransaction ignored. Is this
> >> really needed? Can't we just have a endTransaction in a finally
> >> clause? Am I missing something here? Probably, but I thought I
> >> would ask.
> >>
> >> Sorry, if it is covered in the docs and missed or didn't understand it.
> >>
> >> Al
> >>
> >> Clinton Begin wrote:
> >> > Hi everyone,
> >> >
> >> > Reading through the original thread, there is more than one person
> >> > confused by sessions and transactions, so here's some clarification.
> >> >
> >> > There are four levels of control you can have over iBATIS
> >> > transactions. They are:
> >> >
> >> > #1 First is single statement, automatic transaction. In this case,
> >> > you execute one statement that gets committed (or rolled back)
> >> > automatically by iBATIS. This behaves like JDBC "auto-commit", but it
> >> > definitely doesn't use it. iBATIS always explicitly calls
> >> > commit/rollback. An example of this single statement approach is:
> >> >
> >> > sqlMapper.insert("insertPerson",somePerson);
> >> >
> >> > You don't need a try/finally block or anything. It's all self
> >> > contained. This is one transaction.
> >> >
> >> > #2 The second is multi-statement manual transaction mode. In this
> >> > case you have multiple statements you want to succeed or fail as a
> >> > group. If one statement fails, they all get rolled back. This is the
> >> > most common case for update statements, but can also improve the
> >> > performance and consistency of multiple queries in some cases. The
> >> > example is:
> >> >
> >> > try {
> >> > sqlMapper.startTransaction();
> >> > sqlMapper.insert("insertPerson",somePerson);
> >> > sqlMapper.update("updatePerson",someOtherPerson);
> >> > sqlMapper.delete("deletePerson",anotherPerson);
> >> > sqlMapper.commitTransaction();
> >> > } finally {
> >> > sqlMapper.endTransaction();
> >> > }
> >> >
> >> > There's no explicit call to rollback(). iBATIS knows if you've called
> >> > commit() indicating a successful transaction, otherwise it calls
> >> > rollback. This allows you to use try/finally semantics instead of
> >> > try/catch (which can get messy). You must ensure that this is always
> >> > in a try/finally block as above, otherwise you risk connection leaks.
> >> >
> >> > #3 The third approach is to manage sessions manually. In the last two
> >> > cases sessions were managed automatically. Sometimes you need to do
> >> > this for greater control of the broader iBATIS usage scope, but you
> >> > might also use it to pass your own connection to iBATIS (openSession()
> >> > can take a connection as a parameter). Here's an example:
> >> >
> >> > SqlMapSession session = sqlMap.openSession()
> >> > try {
> >> > session.startTransaction()
> >> > session.insert("insertPerson",somePerson);
> >> > session.update("updatePerson",someOtherPerson);
> >> > session.delete("deletePerson",anotherPerson);
> >> > session.commitTransaction();
> >> > } finally {
> >> > try {
> >> > session.endTransaction();
> >> > } finally {
> >> > session.close();
> >> > }
> >> > // Generally your session scope would be in a wider context and
> >> > therefore the
> >> > // ugly nested finally block above would not be there. Realize that
> >> > sessions
> >> > // MUST be closed if explicitly opened (via openSession()).
> >> > }
> >> >
> >> > As you can see, there's definitely more work and more code involved
> >> > with managing sessions manually...it's therefore pretty rare. If you
> >> > do, you'll usually hide it in some abstract class or perhaps even in a
> >> > separate layer of the application. As the comment above says, doing
> >> > so will also avoid the need for a nested try/finally block (in C#
> >> > using blocks make this a lot cleaner too!).
> >> >
> >> > #4 Finally, there's 3rd Party session/transaction management. This is
> >> > the case if you're using Spring DAO, iBATIS DAO, or some other higher
> >> > level persistence framework that has an iBATIS "plug-in". I won't
> >> > bother with an example, as you're better off looking them up. The one
> >> > we generally recommend is Spring DAO.
> >> >
> >> > I hope that helps. This is all documented both in the JavaDocs and
> >> > the user guide (this is almost a cut and paste from the javadoc). Let
> >> > us know if and how we can make it more clear.
> >> >
> >> > Cheers,
> >> > Clinton
> >> >
> >> > On 1/22/07, Clinton Begin <cl...@gammagarage.com> wrote:
> >> >> Cornel,
> >> >>
> >> >> Richard is right. You're unfortunately mistaken. The following
> >> is an
> >> >> excerpt from the documentation you responded with:
> >> >>
> >> >> 'If a connection is in auto-commit mode, then all its SQL statements
> >> >> will be executed and committed as individual transactions. Otherwise,
> >> >> its SQL statements are grouped into transactions that are terminated
> >> >> by a call to either the method commit or the method rollback."
> >> >>
> >> >> iBATIS always commits or rolls back transactions explicitly with
> >> >> commit() and rollback().
> >> >>
> >> >> Clinton
> >> >>
> >> >> On 1/22/07, Cornel Antohi <ca...@kepler-rominfo.com> wrote:
> >> >> >
> >> >> >
> >> >> > Hi Richard,
> >> >> >
> >> >> > I do not agree with you:
> >> >> >
> >> >>
> >> http://java.sun.com/j2se/1.3/docs/api/java/sql/Connection.html#setAutoCommit(boolean)
> >>
> >> >>
> >> >> >
> >> >> > Thank you,
> >> >> > Cornel
> >> >> >
> >> >> > ----- Original Message -----
> >> >> > From: Yee, Richard K CTR DMDC
> >> >> > To: 'user-java@ibatis.apache.org'
> >> >> >
> >> >> > Sent: Monday, January 22, 2007 6:42 PM
> >> >> > Subject: RE: Autocommit not properly handled in Ibatis.
> >> >> >
> >> >> >
> >> >> > Antohi,
> >> >> > It looks to me that the code does exactly what Clinton says. If
> >> >> autocommit
> >> >> > is on, iBATIS turns it off and thus does not use autocommit to
> >> commit
> >> >> > changes to the DB.
> >> >> >
> >> >> > -Richard
> >> >> >
> >> >> >
> >> >> >
> >> >> > -----Original Message-----
> >> >> > From: Cornel Antohi [mailto:cantohi@kepler-rominfo.com]
> >> >> > Sent: Monday, January 22, 2007 2:37 AM
> >> >> > To: user-java@ibatis.apache.org
> >> >> > Subject: Re: Autocommit not properly handled in Ibatis.
> >> >> >
> >> >> >
> >> >> > Hi Clinton,
> >> >> >
> >> >> > 1) What do you mean by "iBATIS never uses AutoCommit"? Here is what
> >> >> I found
> >> >> > in:
> >> >> >
> >> >> > com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransaction
> >> >> > --> private void init() throws SQLException, TransactionException
> >> >> > // AutoCommit
> >> >> > if (connection.getAutoCommit()) {
> >> >> > connection.setAutoCommit(false);
> >> >> > }
> >> >> >
> >> >> >
> >> >> > Thank you,
> >> >> > Cornel
> >> >> >
> >> >> > ----- Original Message -----
> >> >> > From: "Clinton Begin" <cl...@gmail.com>
> >> >> > To: <us...@ibatis.apache.org>
> >> >> > Sent: Friday, January 19, 2007 8:52 AM
> >> >> > Subject: Re: Autocommit not properly handled in Ibatis.
> >> >> >
> >> >> > A few things:
> >> >> >
> >> >> > 1) iBATIS never uses AutoCommit.
> >> >> >
> >> >> > 2) setCommitRequired has nothing to do with AutoCommit. iBATIS
> >> uses
> >> >> > deferred commits to avoid unecessary commits when no non-queries
> >> have
> >> >> > been issued. And setCommitRequired is actually parameterized
> >> and can
> >> >> > be set with <transactionManager ... commitRequired="true">
> >> >> >
> >> >> > 3) You'll need to post your code so we can see what it's doing.
> >> Are
> >> >> > you calling startTransaction()? Are you using
> >> setUserConnection? Or
> >> >> > openSession(conn)?
> >> >> >
> >> >> > I'm sure with the right information we can resolve this for you
> >> >> easily.
> >> >> >
> >> >> > Clinton
> >> >> >
> >> >> > On 1/18/07, Yuvraj Shinde <Yu...@sos.sungard.com> wrote:
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > > Hi all,
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > > I want to know how to handle auto commit in ibatis.if I am
> >> >> saving two
> >> >> > > records and if I get an exception while saving second record the
> >> >> first
> >> >> > > record saved should be rolled back.
> >> >> > >
> >> >> > > But ibatis is saving the first record. How I should handle this
> >> >> even
> >> >> > > though the auto commit property is explicitly set to false.
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > > Even though AutoCommit value is set to false. Rollback of
> >> >> Transaction
> >> >> > is
> >> >> > > not working.
> >> >> > >
> >> >> > > I found one Issue in GeneralStatement.java.
> >> >> > >
> >> >> > > On line 52 request.getSession().setCommitRequired(true);
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > > Here Auto commit is hard coded it should be parameterized so
> >> >> that it
> >> >> > will
> >> >> > > take value from "Auto commit" property of SqlMapConfig.xml.
> >> >> > >
> >> >> > > Please correct me if I am wrong.please send me a solution.
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > > Regards
> >> >> > >
> >> >> > > Yuvrajs
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > > Yuvraj Shinde * Senior Software Engineer - Zainet* SunGard *
> >> >> Offshore
> >> >> > > Services *
> >> >> > > Pride Portal,CTS No 103A/5A/1A/1B Bhamburda,Senapati Bapat Road,
> >> >> > > shivajinagar,Pune 411016
> >> >> > > Tel Direct +91 20 66248045 * Main +91 20 66248000 * Fax +91 20
> >> >> 25606222
> >> >> > > yuvraj.shinde@sos.sungard.com * www.sungard.com
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > > Success is never ending and failure is never final.
> >> >> > >
> >> >> > >
> >> >>
> >> >
> >>
> >>
> >
>
>