Thanks for the tips, Jeff. It appears, however, that although the
iBATIS "startTransaction" will not start another transaction if a JTA
transaction exists, it will still thrown an exception. (I'd assumed -
incorrectly - that all of the transaction handling would be handed off
to JTA).
Anyway, I seem to be on the right track now!
Cheers,
Alistair.
On 08/04/2008, Jeff Butler <[EMAIL PROTECTED]> wrote:
> 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.
> >
>
>