我有EmployeeDAOImpl.java和DepartmentDAOImpl.java。现在我从数据服务层调用这两个。 EmployeeDAO和DepartmentDAO是界面,他们只有简化CRUD方法。在Service层中,我在方法中有两个方法调用createEmployee(Employee employee)和createDepartment(Department department)。这两个调用应该在同一个事务中,这意味着只有在2个调用成功后才能关闭连接。现在,您是否有人知道如何提供连接。我不想在DepartmentDAOImpl和EmployeeDAOImpl的构造函数中提供连接。另外我不想使用Spring AOP或ThreadLocale,有没有解决办法呢?
答案 0 :(得分: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将是一个好处。它将消除样板代码。这是你的选择。
答案 1 :(得分:1)
我不想使用Spring AOP或ThreadLocale
不幸的是(?)这就是Spring处理事务和连接的方式 - (简而言之)一旦从非事务上下文中输入@Transactional
方法,它就会在ThreadLocal
中将该事务的数据库连接置于负责状态。这样,该事务中的每个方法都使用相同的连接,因此使用相同的事务。这完全是transaprent,您只需使用DataSource
抽象或JdbcTemplate
(优雅地隐藏这种复杂性)。
请注意,在多线程环境中完全断开传递连接作为构造函数参数。您应该通过DataSource
。 Spring(或者就此而言的EJB)将处理低级别的东西。
稍微更好的方法是将Connection
传递给每个DAO的每个方法。但这就是20世纪90年代......你能详细说明你不喜欢Spring方法吗?
答案 2 :(得分: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);
}
}
}
然后您的服务只能使用Manager类。而不必担心连接管理...每个“表”都有一个Manager和要使用的DAO是缺点。