DAO pattern - where do transactions fit in?

Boden picture Boden · Apr 21, 2009 · Viewed 9.9k times · Source

So I've got this generic DAO thing going on and at face value it appears to be ok. It's basically modeled after the CaveatEmptor sample application from the Hibernate guys.

On top of that I have a business layer...the guts of the application. It's completely unaware of any specific DAO implementation.

Everything up to this point seems fine, until I start thinking about transactions. If transactions are left to the client to implement, then how in the world do I maintain the nice separation I've got going on between my layers? That is, I'm using Hibernate at the moment, and I don't really feel much like adding hibernate-specific transactions to my business layer code.

I could create a simple transaction interface with begin, commit, and rollback methods and pass an implementation to my business layer...but...I'm not sure...

So here is the challenge: can you recommend a way for me to do this without using the word Spring (or EJB, or any other additional framework)?

Answer

Nicolas Dorier picture Nicolas Dorier · Apr 21, 2009

I remember that Martin Fowler advices to keep the control of the transaction in the business layer because transaction is a business problem. (If you design a BankAccount class, a transaction is part of the domain language).

You can try to implement a TransactionScope as in .NET it works something like that

using (TransactionScope ts = new TransactionScope())
{
  ...
}

It's the same thing as (not exactly but if you are a Java guy, it's more explicit to you)

TransactionScope scope = new TransactionScope();
try
{
 ...
 scope.Commit();
}
catch(Exception ex)
{
  scope.Rollback();
  throw;
}

To decouple your business layer from any DAO technologies you can add a TransactionFactory in your domain language, which return a ITransactionScope (an interface) that you have defined with a Commit and Rollback methods. This way your domain layer is not bound to your DAO layer, only a concrete implementation of TransactionFactory is.

ITransactionScope scope = transactionFactory.CreateTransaction();
try
{
 ...
 scope.Commit();
}
catch(Exception ex)
{
  scope.Rollback();
  throw;
}