ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Prashanth Sukumaran <prashanthsukuma...@yahoo.com>
Subject RE: Transaction question
Date Thu, 18 Aug 2005 16:14:48 GMT
Hi,

Do we really have to do all this in the name of reusability.  Can't you change the way you
code? 
Can't you overload/refactor a method and have the transaction externalized.

Assume you have 

methodA
startTransaction();
     // do some business logic.
     callDAO.doSomething();
endTransaction();

Instead change it to

methodA [    // All that methodA is used is for now Transaction Encapsulation and not anything
else.
    startTransaction()
    methodB
    endTransaction()
]

methodB [
    // do some business logic.
    callDAO.doSomething();
]

In a different service manager instead of calling the methodA and hence having nested
transactions, can't you call methodB instead.

Rgds

Prashanth Sukumaran.

 

--- "Barnett, Brian W." <brian.barnett@pearson.com> wrote:

> Niels,
> Thanks for the info. Maybe I am not totally understanding how your modified
> code works, but is it meant to handle nested transactions?
> 
> If a transaction has already been started, then your modified code will
> simply call invoke. I understand that. What happens when a nested
> transaction calls commitTransaction()? (Like doSomethingElse() calling
> doSomething() in the sample code below.) commitTransaction() gets called
> twice in this example. I believe it will throw an exception.
> 
> What I was considering was to add a ThreadLocal transactionCounter variable
> to DaoContext. start, commit and end transaction methods might look
> something like this:
> 
>   public void startTransaction() {
>     transactionCounter++;          // <-- NEW LINE OF CODE
>     if (transactionCounter == 1) { // <-- NEW LINE OF CODE
>       if (state.get() != DaoTransactionState.ACTIVE) {
>         DaoTransaction trans = transactionManager.startTransaction();
>         transaction.set(trans);
>         state.set(DaoTransactionState.ACTIVE);
>         daoManager.addContextInTransaction(this);
>       }
>     }                              // <-- NEW LINE OF CODE
>   }
> 
>   public void commitTransaction() {
>     if (transactionCounter == 1) { // <-- NEW LINE OF CODE
>       DaoTransaction trans = (DaoTransaction) transaction.get();
>       if (state.get() == DaoTransactionState.ACTIVE) {
>         transactionManager.commitTransaction(trans);
>         state.set(DaoTransactionState.COMMITTED);
>       } else {
>         state.set(DaoTransactionState.INACTIVE);
>       }
>     }                              // <-- NEW LINE OF CODE
>   }
> 
>   public void endTransaction() {
>     try {                            // <-- NEW LINE OF CODE
>       if (transactionCounter == 1) { // <-- NEW LINE OF CODE
>         DaoTransaction trans = (DaoTransaction) transaction.get();
>         if (state.get() == DaoTransactionState.ACTIVE) {
>           try {
>             transactionManager.rollbackTransaction(trans);
>           } finally {
>             state.set(DaoTransactionState.ROLLEDBACK);
>             transaction.set(null);
>           }
>         } else if (transactionCounter == 1) {
>           state.set(DaoTransactionState.INACTIVE);
>           transaction.set(null);
>         }
>       }                     // <-- NEW LINE OF CODE
>     } finally {             // <-- NEW LINE OF CODE
>       transactionCounter--; // <-- NEW LINE OF CODE
>     }                       // <-- NEW LINE OF CODE
>   }
> 
> The idea being that the transaction related logic only executes when we are
> dealing with the first transaction bracket that was opened. I haven't
> actually tried this out, but I think I will. Let me know if you, or anyone
> else, sees any problems with this approach.
> 
> Thanks,
> Brian Barnett
> 
> -----Original Message-----
> From: Niels Beekman [mailto:n.beekman@wis.nl] 
> Sent: Wednesday, August 17, 2005 3:00 PM
> To: user-java@ibatis.apache.org
> Subject: RE: Transaction question
> 
> 
> Hi,
> 
> I'm facing this exact same problem however in a somewhat different context,
> see the following archived thread:
> 
> http://www.mail-archive.com/ibatis-user-java@incubator.apache.org/msg025
> 80.html
> 
> http://www.mail-archive.com/user-java@ibatis.apache.org/msg00036.html
> 
> I recently restarted my investigation into this problem and have tried some
> hacks in the iBATIS code, the changes were made in DaoProxy.java (which
> proxies DAO-interfaces to provide transaction-semantics) and DaoContext.java
> (which handles the transactions itself). Of course this is rather messy, but
> I really do not like the SavePoint-support mentioned in the thread above, I
> think it is rather a workaround than a solution.
> 
> Anyway, my changes (totally unverified, without any guarantees) in package
> com.ibatis.dao.engine.impl:
> 
> DaoContext.java, added isTransactionRunning():
> 
> public boolean isTransactionRunning() {
>   return transaction.get() != null;
> }
> 
> DaoProxy.java, modified invoke(): see attached file.
> 
> This seems to work pretty good in my case, however further investigation is
> required.
> 
> I hope the iBATIS devteam can comment on my solution, whether you think it
> will work, or when you believe it really sucks :)
> 
> Greetings,
> 
> Niels
> 
> -----Original Message-----
> From: Barnett, Brian W. [mailto:brian.barnett@pearson.com] 
> Sent: woensdag 17 augustus 2005 22:00
> To: 'user-java@ibatis.apache.org'
> Subject: Transaction question
> 
> What are some good options to deal with the following:
> 
> ServiceClass1
> public void doSomething() {
> 	try {
> 		daoManager.startTransaction();
> 		// Write some stuff to a database
> 		daoManager.commitTransaction();
> 	} catch (Exception e) {
> 		throw e;
> 	} finally {
> 		daoManager.endTransaction();
> 	}
> }
> 
> ServiceClass2
> public void doSomethingElse() {
> 	try {
> 		daoManager.startTransaction();
> 		ServiceClass1 sc1 = new ServiceClass1();
> 		sc1.doSomething();
> 		// Write some stuff to a database
> 		daoManager.commitTransaction();
> 	} catch (Exception e) {
> 		throw e;
> 	} finally {
> 		daoManager.endTransaction();
> 	}
> }
> 
> The doSomethingElse() method will fail because startTransaction() gets
> called twice. I need a good way to be able to re-use business logic methods
> in different, or the same, service layer classes.
> 
> One thing I have done in the past is create a whole new layer, essentially a
> service delegate, where I have moved all the transaction logic to. I didn't
> like that too much because it was just a huge proliferation of methods just
> to solve the "no nested transaction" problem.
> 
> I have also passed flags into methods to indicate if a transaction has
> already been started, but passing flags is messy to say the least.
> 
> Any great ideas out there?
> 
> TIA,
> Brian Barnett
> 
> ************************************************************************
> **** 
> This email may contain confidential material. 
> If you were not an intended recipient, 
> Please notify the sender and delete all copies. 
> We may monitor email to and from our network. 
> ************************************************************************
> ****
> 
> **************************************************************************** 
> This email may contain confidential material. 
> If you were not an intended recipient, 
> Please notify the sender and delete all copies. 
> We may monitor email to and from our network. 
> ****************************************************************************
> 



		
____________________________________________________
Start your day with Yahoo! - make it your home page 
http://www.yahoo.com/r/hs 
 

Mime
View raw message