Is it poor design for DAOs to manage transactions?
I've been reading about the sun blueprint GenericDAO
implementation and Gavin King's take on this for use with Hibernate. It seems he doesn't mention anything about transaction handling:
public abstract class GenericHibernateDAO<T, ID extends Serializable> {
protected Session getSession() {
return HibernateUtil.getSessionFactory().getCurrentSession();
}
public T makePersistent(T entity) {
getSession().saveOrUpdate(entity);
return entity;
}
}
I'm puzzled as to whe开发者_Go百科re I should put the start/end of the transaction. Currently they are inside the DAOs that extend this GenericHibernateDAO
public class FooHibernateDAO extends GenericHibernateDAO<Foo, Long> {
public Foo saveFoo(Foo foo) {
getSession().beginTransaction();
makePersistent(foo);
getSession().getTransaction().commit();
}
}
Should the transaction handling be managed by the caller of the DAO in the application tier?
Generally the best practice is to manage transactions in service layer not in DAO layer. Each DAO method generally handles one specific operation and a service method aggregates them in one transaction.
Transactions should be managed in the application tier. Say for example you had an AccountDAO:
public class AccountDAO {
public void DebitAccount( int accountId, int dollars ) {
}
public void CreditAccount( int accountId, int dollars ) {
}
}
If I wanted to transfer money between accounts, I would call DebitAccount
on one account and CreditAccount
on another. I would want these calls to happen in the same transaction. The DAO can't possibly know that, but the application tier would.
If transactions were managed at the DAO tier, you would need to create another TransferMoney
method on the DAO to do it in one transaction. This would eventually bloat your DAO tier and, for complex operations, bring in business logic that probably shouldn't be there. And it gets even messier if you have an operation that requires multiple DAOs to be involved in a single transaction.
精彩评论