ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Clinton Begin" <clinton.be...@gammagarage.com>
Subject Re: Proper transaction code pattern
Date Mon, 22 Jan 2007 19:16:58 GMT
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 <asapp@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 <asapp@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 <clinton.begin@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 <cantohi@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" <clinton.begin@gmail.com>
> >> >> > To: <user-java@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 <Yuvraj.Shinde@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.
> >> >> > >
> >> >> > >
> >> >>
> >> >
> >>
> >>
> >
>
>

Mime
View raw message