ThreadLocal中放置connection, 保证事务中的DAO类获取的都是同一个connection,这样才保证事务。
下面是网上找到的一个具体的例子http://www.pin5i.com/showtopic-26854.html
-----------------------------------------------------------------------------------
通常我们会把事务处理放在业务层。
[1]引子
比如:
业务逻辑方法
- public A bussinessMethod(){
- DaoA a = new DaoA();
- a.udpate();
- DaoB b = new DaoB();
- b.update;
- }
假设,上面的事务是自动提交的。
那么,我们就可以什么不考虑。但是有一个问题,创建DAO对象的时候两个对象用的是不同的Connection对象。
再假定我们的取得连接的代码是
- public Connection getConnection(String username, String password)
- throws SQLException {
- Connection con = DriverManager
- .getConnection(conStr, username, password);
- return con;
- }
这个方法的一个调用。
那么如果,我们需要自己控制事务的开始和结束。
如何控制呢。
也许又有了新的方法
- public A bussinessMethod(){
- DaoA a = new DaoA();
- a.beginTx();
- a.udpate();
- a.endTx();
- a.close();
- DaoB b = new DaoB();
- b.beginTx();
- b.update;
- b.endTx();
- b.close();
- }
这样我们就控制了事务,并且我们也只有这样才能实现,因为,不同的DAO取得的是不同的Connection对象。
[2]问题
那么怎么才能实现两个或多个DAO用同一个事务来控制呢?
首先就要解决一个根本问题,我们在一个事务中,不同的DAO取得的是同一个Connection,这个要怎么实现呢。我们想到了TheadLocal.
[3]方案
因为当一个业务逻辑要对多个DAO进行处理的时候,此操作属于同一个线程内。所以,我们希望能把此Connection放在线程内,或者和线程有关联。
第一个方案,可以用Map来使现。
就是Map<Thread,Connection>
但是这个map维护起来比较麻烦,如果一直put的话,那么这个map随着系统的运行就会越来越大。
第二个方案,就是用ThreadLocal
在任何一个线程内都可以用ThreadLocal来保存一个变量的copy,这样,如果此对象存在,就可以直接取用。
如果把Connection存在ThreadLocal也一样。
所以,在同一个线程内,就可以保证取得到的是同一个Connection.
[4]实现
- private static ThreadLocal<Connection> localCon = new ThreadLocal<Connection>();
- public final static Connection getConnection() throws SQLException {
- Connection con = localCon.get();
- if(con==null||con.isClosed()){
- con = new OracleJdbcDatasource().getConnection();
- localCon.set(con);
- }
- return con;
- }
这样就实现了上面的问题。
[5]新的事务管理
- public A bussinessMethod(){
- DaoA a = new DaoA();
- DaoB b = new DaoB();
- a.beginTx();
- a.udpate();
- b.beginTx();
- b.update;
- a.endTx();
- a.close();
- // b.endTx();
- // b.close();
- 能实现一样的效果
- }
上面的黑体部分,就可以实现对事务的统一管理。