己的 conntionconn=getConnection(),然后还跑到 Service 层里去关这个 connection(那
关什么,关个 P 关!)。
当然,如果你说你在写法上绝对 promise 绝对注意这样的问题不会发生,但是我们来看看
下面的这种做法,是否会比上面这个写法更好呢?
2.3 Spring 中的做法
先来看 Spring 中的写法。
大家应该都很熟悉 Spring 中的写法了,来看一下它是怎么解决的。
Service 层
public void serviceMethod(){
try{
%%% //aop 自动加入 connection,并且将 conn.setAutoCommit(false);
dao1.doSomething();
dao2.doSomething();
dao3.doSomething();
}catch(Exception e){
%%% //aop 自动加入 rollback
}finally{
%%% //aop 自动加入 conn.setAutoCommit(true)
%%% //aop 自动加入 conn.close();
}
%
这边我们不讲 AOP,因为用类反射结合 xml 很容易将 aop 自动。。。这些东西加入我们的
代码中去是不是?我们只管写 dao 方法,service 方法,不需要关心在哪边 commit 哪边
rollback 何时 connection,spring 的声明式事务会帮我们负责,这种风格我们称为“优雅”,
各层间耦合度极大程度上的降低,封装性好。
因此,我们可以总结出下面这些好处:
²% Service 层的方法只管开启事务(如果讲究点的还会设一个 Transaction);
²% 在该 Service 层中的所有 dao 使用该 service 方法中开启的事务(即 connection);
²% Dao 中每次只管 getCurrentConnection(获取当前的 connection),与进行数据处理
²% Dao 层中如果发生错误就抛回 Service 层
²% Service 层中接到 exception,在 catch{}中 rollback,在 try{}未尾 commit,在 finally 块中
关闭整个 connection。
这。。。就是我们所说的 ThreadLocal。
举个更实际的例子再次来说明 ThreadLocal:
我们有 3 个用户访问同一个 service 方法,该 service 方法内有 3 个 dao 方法为一个完整事
务,那么整个 web 容器内只因该有 3 个 connection,并且每个 connection 之间的状态,彼
此“隔离”。
我们下面一起来看我们如何用代码实现类似于 Spring 的这种做法。
首先,根据我们的 ThreadLocal 的概念,我们先声明一个 ConnectionManager 的类。
2.4利用 ThreadLocal 制作 ConnectionManager
public class ConnectionManager {