正确实现一个 dao 类来管理事务

Posted

技术标签:

【中文标题】正确实现一个 dao 类来管理事务【英文标题】:implementing a dao class properly to manage transactions 【发布时间】:2011-10-10 06:52:26 【问题描述】:

我正在开发一个通过 hibernate 调用数据库后端的 java web 应用程序。我使用 servlet、jsp 和 tomcat 进行测试/部署。大多数关于 java-ee 的书籍建议使用 Dao 类进行数据库调用。根据书中给出的示例(Gary Mak 的 Hibernate 食谱),我创建了一个通用基类和一个特定的子类,如下所示。

class BaseDao
   private Class persistentClass;
   public BaseDao(Class persistentClass) 
        super();
        this.persistentClass = persistentClass;
    
   public Object findById(Long id) 
        SessionFactory factory = HibernateUtil.getSessionFactory();
        Session session = factory.openSession();
        Object object = null;
        try 
            object = (Object) session.get(persistentClass, id);
            return object;
        
        finally 
            session.close();
        
    

    @Override
    public void saveOrUpdate(Object obj) 
        SessionFactory factory = HibernateUtil.getSessionFactory();
        Session session = factory.openSession();
        Transaction tx = null;
        try 
        tx = session.beginTransaction();
        session.saveOrUpdate(obj);          
        tx.commit();
        catch(HibernateException e)
            if (tx != null) 
                       tx.rollback();   

             
             throw e;
        finally 
            session.close();
        

    


    class SaleOrderDao extends BaseDao
        public SaleOrderDao() 
            super(SaleOrder.class);
        
        @Override
       public SaleOrder findSaleOrderById(Long saleOrderId)            
                SaleOrder so =  (SaleOrder)findById(saleOrderId);
                return  so;

        
        @Override
        public void saveOrUpdateSaleOrder(SaleOrder so)

                    saveOrUpdate( so);

            

    

在浏览这个论坛的帖子时,我遇到了 Ryan Stewart 的 advice 不建议以 dao 方法开始和结束交易。遗憾的是,我的项目不使用任何网络支持事务管理的框架..我仅限于使用 jsp、servlet 和 servlet 容器..

有什么方法可以重写我的 dao 实现,以便可以正确管理事务..我从我读过的那些书中找不到这方面的任何内容..

希望有人能帮助我提出建议

真诚的,

吉姆

【问题讨论】:

使用 spring 并完成它。否则,您将忽略一个可免费获得、经过测试且有据可查的现成解决方案,而倾向于花时间拼凑一些未经测试和无文档的东西。 内森是正确的,假设你可以使用弹簧。除此之外,您了解什么是交易吗?我不是想屈尊俯就,但理解这一点很重要,特别是如果你打算自己动手的话。 Wikipedia 的描述冗长但准确:en.wikipedia.org/wiki/Database_transaction 简而言之:txn 是一个或多个数据库查询,必须全部通过或回滚。考虑一家银行将货币从一个账户转移到另一个账户。一项计数必须记入借方,另一项记入贷方。如果一个帐户被借记但贷记失败,则您已将钱汇入“虚空”。 【参考方案1】:

通常不应在 DAO 中处理事务。它们应该由服务层处理。一种服务方法可能包括多个 DAO 调用,它们都在同一个事务中。

Spring(以及其他 DI 框架)允许您通过简单地使用 @Transactional 注释您的服务方法来做到这一点。如果没有 spring,你仍然可以在服务层手动执行此操作

【讨论】:

我有一个问题。我有 3 个用于 3 个不同 mysql 模式的 DAO 类。它们都有不同的数据源、会话工厂和事务管理器。我需要在一个事务下更新所有 3 个模式的表。这些 dao 调用是通过一种服务方法进行的。我无法找出如何为该服务方法提供所有 3 个事务管理器。我正在使用弹簧和休眠。有什么想法吗? 这值得一个单独的问题 谢谢博卓。它会作为一个单独的问题发布吗?

以上是关于正确实现一个 dao 类来管理事务的主要内容,如果未能解决你的问题,请参考以下文章

马士兵Spring-声明式事务管理-annotation

Spring的事务管理

[转]Spring的事务管理难点剖析:DAO和事务管理的牵绊

spring的事务管理

Spring框架中是不是有DAO的事务管理?

Spring管理事务配置的五种方式