-1

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

4

3 回答 3

1

我不想使用 Spring AOP 或 ThreadLocale

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

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

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

于 2013-01-08T18:54:31.847 回答
1

您没有解释为什么不想提供与 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 将在这里受益。它将消除样板代码。这是你的选择。

于 2013-01-08T18:53:28.240 回答
0

我正在进行一个项目,人们不喝 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);
      }
   }
}

然后你的服务可以只使用管理器类..而不用担心连接管理......每个“表”都有一个管理器,而要使用的 DAO 是缺点。

于 2018-08-16T20:11:03.377 回答