iBATIS does not support nested transactions.  Take a look at the class
com.ibatis.sqlmap.engine.transaction.jta.JtaTransaction
to see what's going on.

If a JTA transaction already exists...

1. The iBATIS "startTransaction" will not start another transaction
2. The iBATIS commit does nothing
3. The iBATIS rollback marks the transaction for rollback, but does not
rollback itself

When there are externally managed transactions, the iBATIS rollback will
mark the external transaction for rollback, but the other two methods do,
essentially, nothing.

Jeff Butler

On Tue, Apr 8, 2008 at 9:44 AM, Alistair Young <[EMAIL PROTECTED]>
wrote:

> Once again I seem to have found a solution shortly after asking the
> question...
>
> On 08/04/2008, Alistair Young <[EMAIL PROTECTED]> wrote:
> > [ ... snip ... ]
> >
> >        // start a transaction
> >        // [iBATIS starts a new JTA transaction...?]
> >        sqlMapClient.startTransaction();
> >
> >        // ... do some database processing ...
> >
> >        // start an inner transaction
> >        // [iBATIS joins the existing JTA transaction...?]
> >        sqlMapClient.startTransaction();
> >
> >        // ... do some more database processing ...
> >
> >        // abandon the inner transaction
> >        // [iBATIS issues setRollbackOnly on JTA transaction...?]
> >        sqlMapClient.endTransaction();
> >
> >        // commit the outer transaction
> >        // [iBATIS issues commit on JTA transaction...?]
> >        sqlMapClient.commitTransaction();
> >
> >  with the final result that the database is unchanged.  However,
> >  instead, I get an exception on my second call to startTransaction()
> >  complaining that a transaction is already started.
> >
> >  [ ... snip ... ]
>
> After a bit of experimentation, I think that I need to explicitly
> start the JTA transaction outside of the iBATIS transactions.  The
> following does what I'd expected:
>
>       // start a JTA transaction
>       Context ctx = new InitialContext();
>       UserTransaction ut =
> (UserTransaction)ctx.lookup("java:comp/UserTransaction");
>       ut.begin();
>
>       // start an iBATIS transaction
>       // [iBATIS joins the JTA transaction]
>       sqlMapClient.startTransaction();
>
>       // ... do some database processing ...
>
>       // commit the iBATIS transaction
>       // [iBATIS does not actually commit to the db]
>       sqlMapClient.commitTransaction();
>
>       // start another iBATIS transaction
>       // [iBATIS joins the JTA transaction]
>       sqlMapClient.startTransaction();
>
>       // ... do some more database processing ...
>
>       // abandon the iBATIS transaction
>       // [iBATIS issues setRollbackOnly on JTA transaction]
>       sqlMapClient.endTransaction();
>
>       // commit the JTA transaction
>       try {
>              ut.commit();
>       } catch (RollbackException x) {
>              // will be raised because the commit did
>              // not take place (since the second iBATIS
>              // transaction was cancelled)
>       }
>
> Please feel free to suggest a better way, if one should exist!
>
>
> Alistair.
>

Reply via email to