2010-06-24 73 views
8

我一直在阅读有关太阳蓝图GenericDAO的实现和Gavin King的采用这个与Hibernate一起使用。看来他没有提到有关事务处理的事情:DAO管理交易的设计很差吗?

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; 
    } 
} 

我困惑的是,我应该把交易的开始/结束。目前,他们是扩大这种GenericHibernateDAO

public class FooHibernateDAO extends GenericHibernateDAO<Foo, Long> { 
    public Foo saveFoo(Foo foo) { 
     getSession().beginTransaction(); 
     makePersistent(foo); 
     getSession().getTransaction().commit(); 
    } 
} 

如果该交易处理在应用层上的DAO的调用者管理的DAO的内部?

回答

16

通常,最佳做法是管理服务层中不在DAO层的事务。每个DAO方法通常处理一个特定的操作,并且一个服务方法在一个事务中聚合它们。

+0

这就是它+1 - 你打我给它 – 2010-06-24 18:02:35

3

事务应该在应用程序层进行管理。例如说,你有一个AccountDAO:

public class AccountDAO { 
    public void DebitAccount(int accountId, int dollars) { 

    } 

    public void CreditAccount(int accountId, int dollars) { 
    } 
} 

如果我想帐户间转帐,我会叫上另一DebitAccount一个帐户和CreditAccount。我希望这些调用发生在同一个事务中。 DAO不可能知道这一点,但应用程序层会。

如果事务是在DAO层管理的,则需要在DAO上创建另一个TransferMoney方法才能在一个事务中执行此操作。这最终会使你的DAO层膨胀,并且对于复杂的操作,引入可能不应该存在的业务逻辑。如果您需要多个DAO参与单个事务的操作,它会变得更加混乱。

+0

所以采取类似贷款系统中大量的查询完成,以决定报价,则报价被写入到DB一个例子,你将开始交易在所有的读取之前?此外''GenericDao'没有公开的方法来检索会话以启动事务? – James 2010-06-24 18:20:39

+1

@James - 我会在发生任何写入之前启动事务,但不一定在读取之前。是的,DAO不需要担心交易,所以不需要任何方法。交易将在服务层进行管理。 – 2010-06-24 18:24:39

+0

好的,谢谢你。如果你不介意的最后一两件事 - 服务层开始交易,但为了它做到这一点需要访问一个“会话”,以调用'session.beginTransaction()'。如果它不是提供带有'Session'的服务层的DAO,它来自哪里?静态'SessionFactory'? – James 2010-06-24 18:40:18