【问题标题】:DAO Design Pattern and Connection HandlingDAO 设计模式和连接处理
【发布时间】:2013-01-08 18:50:42
【问题描述】:

我有 EmployeeDAOImpl.java 和 DepartmentDAOImpl.java。现在我从数据服务层调用这两个。 EmployeeDAO 和 DepartmentDAO 是接口,它们只有抽象的 CRUD 方法。在服务层中,我在一个方法中有两个方法调用 createEmployee(Employee employee) 和 createDepartment(Department department)。这 2 个调用应该在同一个事务中,这意味着只有在 2 个调用成功后才能关闭连接。现在你们知道如何提供连接吗?我不想在 DepartmentDAOImpl 和 EmployeeDAOImpl 的构造函数中提供连接。另外我不想使用 Spring AOP 或 ThreadLocale,有什么解决方案吗?

【问题讨论】:

    标签: design-patterns dao


    【解决方案1】:

    我不想使用 Spring AOP 或 ThreadLocale

    不幸的是(?)这就是 Spring 处理事务和连接的方式——(简而言之)一旦你从非事务上下文输入 @Transactional 方法,它会将负责该事务的数据库连接放在 ThreadLocal 中。这样,该事务中的每个方法都使用相同的连接,因此是相同的事务。这完全是透明的,您只需使用DataSource 抽象或JdbcTemplate(优雅地隐藏了这种复杂性)。

    请注意,将连接作为构造函数参数传递在多线程环境中完全被破坏。你应该通过 DataSource 代替。 Spring(或 EJB)将处理低级的东西。

    稍微更好的方法是将Connection 传递给每个DAO 的每个方法。但这是 1990 年代...你能详细说明你不喜欢 Spring 方法的哪些方面吗?

    【讨论】:

    • +1 - 一个写得很好的,深思熟虑的答案。我将支持重新考虑 Spring 的建议。
    【解决方案2】:

    您没有解释为什么不想提供与 DAO 构造函数的连接或使用 Spring AOP 或 ThreadLocale。

    我会说连接获取是事务管理的一部分,这是服务层的责任。它应该为 DAO 提供连接数据库所需的内容。

    你已经说过你不会怎么做,但没有提供关于如何做的想法。

    我会说服务应该从池中获取连接,将其提供给 DAO,管理事务,并在用例完成后将连接返回到池。

    我将把实现细节留给你,因为你不想使用 Spring。可以使用直接 JDBC 来做到这一点。你只需要更加努力地工作。

    如果您坚持不使用 Spring 或 AOP,您的服务代码将如下所示:

    package service;
    
    public class FooServiceImpl implements FooService {
        public void saveFoo(Foo f) {
            Connection connection = null;
            Statement st = null;
            try {
                connection = ConnectionPool.checkout();
                connection.setAutoCommit(false);
                // do something here
                connection.commit();
            } catch (Exception e) {
                rollback(connection);
                e.printStackTrace();
            } finally {
                close(st);
                close(connection);
            }
        }
    }
    

    Spring 和 AOP 将在这里受益。它将消除样板代码。这是你的选择。

    【讨论】:

      【解决方案3】:

      我正在做一个项目,人们不喝 Spring kool-aid...我发现下面的模式对我很有效...

      Service-->*Manager-->DAOs
      

      假设您有 3 个不同的表必须在单个事务中更新(全有或全无)。其中一个表是“父”表,其中子表必须在父保存期间更新。

      public class ParentServive
          private ParentManager parentManager; 
      
          public void save(Parent parent){
               parentManager.save(parent)
          }
      }
      

      创建一个所有 *Manager 类都可以扩展的 DAOManager

      public class DAOManager{
      ...
      ..
        public Connection getConnection()throws DAOException{
        try{
          dataSource.getConnection();
          }catch(SQLException e){
          throw new DAOExceptoin(e);
          }
        }
      
          public Connection getTXConnection()throws DAOException{
           Connection connection  = dataSource.connection;
           connection.setAutoCommit(false);
           return connection;
        }
      
        public void close(Connection connectoin) throws DAOException{
      
        try{
            if ( !connection.getAutoCommit() ){
               connection.setAutoCommit(true);
           }
           connection.close();
           }catch(SQLException e){
            throw new DAOExceptoin(e);
          }
        }
      }
      

      现在您有两个 DAO,父表必须更新它们才能使保存有效,首先创建一个抽象 DAOManager 请注意,我只打开了一个连接,并且可以在所有表​​上回滚或提交...

       public class ParentManager extends DAOManager{
         private ParentDAO parentDAO;
         private ChildOneDAO childOneDAO;
         private ChildTwoDAO childTwoDAO;
      
         public save(Parent parent) throw DAOException{
            Connection connection = null;
      
            try{
            connection = getTXConnection(); 
            ParentDAO parentDAO   = new ParentDAO(connection);
            ChildTwoDAO childTwoDAO = new ChildOneDAO(connection);
            ChildTwoDAO childTwoDAO = new ChildTwoDAO(connection);
      
            parentDAO.save(...)
      
            childOneDAO.save(...)
      
            childTwoDAO.save(..)    
      
      
            connection.commit();
      
            }catch(Exception e){    
              connection.rollback();
            }finally{
            close(connection);
            }
         }
      }
      

      那么您的服务只能使用 Manager 类..而不用担心连接管理...每个“表”都有一个 Manager,而要使用的 DAO 是缺点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-12
        • 1970-01-01
        • 2017-10-26
        • 2012-04-14
        • 2012-08-21
        • 1970-01-01
        相关资源
        最近更新 更多