[转]POJO中使用ThreadLocal实现Java嵌套事务

大多嵌套事务都是通过EJB实现的,现在我们尝试实现对POJO的嵌套事务。这里我们使用了ThreadLocal的功能。

理解嵌套事务

事务是可以嵌套的。所以内层事务或外层事务可以在不影响其他事务的条件下进行回滚或提交。

新建的事务嵌套在外层事务中。如果内层事务完成(不论是回滚或是提交),外层的事务就可以进行回滚或提交,这样的操作并不会影响内层事务。首先关闭最内层的事务,并逐步移动到外层事务。

[转]POJO中使用ThreadLocal实现Java嵌套事务

使用简单的POJO实现

新建如下接口:

[转]POJO中使用ThreadLocal实现Java嵌套事务
1 importjava.sql.Connection;
2  
3 public interface TransactionManager {
4  
5     Connection getConnection();
6     void beginTransaction();
7     void commit();
8     void rollback();
9 }
[转]POJO中使用ThreadLocal实现Java嵌套事务

新建如下事务管理类:

[转]POJO中使用ThreadLocal实现Java嵌套事务
 1 importjava.sql.Connection;
 2 importjava.sql.DriverManager;
 3 importjava.sql.SQLException;
 4 importjava.util.Stack;
 5  
 6 public class TransactionManagerStackImpl implements TransactionManager {
 7      
 8     private Stack<Connection>connections = new Stack<Connection>();
 9  
10     @Override
11     public Connection getConnection() {
12  
13         if (connections.isEmpty()) {
14             this.addConn();
15         }
16  
17         return connections.peek();
18     }
19  
20     @Override
21     public void beginTransaction() {
22         this.addConn();
23     }
24  
25     @Override
26     public void commit() {
27         try {
28             if (connections.peek() != null&& !connections.peek().isClosed()) {
29                 System.out.println(connections.peek().toString() +"--Commit---");
30                 connections.peek().commit();
31                 connections.pop().close();
32             }
33  
34         } catch (SQLException e) {
35             e.printStackTrace();
36         }
37  
38     }
39  
40     @Override
41     public void rollback() {
42         try {
43  
44             if (connections.peek() != null&& !connections.peek().isClosed()) {
45                 System.out.println(connections.peek().toString() +"--Rollback---");
46                 connections.peek().rollback();
47                 connections.pop().close();
48             }
49         } catch (SQLException e) {
50             e.printStackTrace();
51         }
52  
53     }
54  
55     private void addConn() {
56         try {
57             Connection con = this.getMysqlConnection();
58             con.setAutoCommit(false);
59             connections.push(con);
60             System.out.println(con.toString() +"--Conection---");
61         } catch (SQLException e) {
62             e.printStackTrace();
63         }
64          
65     }
66  
67     private Connection getMysqlConnection() {
68         return getConnection("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/testdb", "test", "test12345");
69     }
70  
71     private Connection getConnection(String driver, String connection,
72             String user, String password) {
73  
74         try {
75             Class.forName(driver);
76             return DriverManager.getConnection(connection, user, password);
77         } catch (ClassNotFoundException e) {
78             e.printStackTrace();
79         } catch (SQLException e) {
80             e.printStackTrace();
81         }
82  
83         returnnull;
84  
85     }
86 }
[转]POJO中使用ThreadLocal实现Java嵌套事务

到这里,我们创建了一个栈(Stack)

[转]POJO中使用ThreadLocal实现Java嵌套事务
private Stack<Connection> connections = new Stack<Connection>();
[转]POJO中使用ThreadLocal实现Java嵌套事务

事务遵循栈“先进后出”的原则,通过栈存储事务的连接:

[转]POJO中使用ThreadLocal实现Java嵌套事务
public void beginTransaction()
[转]POJO中使用ThreadLocal实现Java嵌套事务

beginTransaction()用于开启一个新的事务,并将连接加入到栈中。自动提交设置为否:

[转]POJO中使用ThreadLocal实现Java嵌套事务
public Connection getConnection()
[转]POJO中使用ThreadLocal实现Java嵌套事务

getConnection()获得当前事务的连接。如果连接为空,则创建新的连接并将其加入到栈:

[转]POJO中使用ThreadLocal实现Java嵌套事务
public void commit()
[转]POJO中使用ThreadLocal实现Java嵌套事务

提交当前的事务,之后关闭连接,并将其从栈中移除:

[转]POJO中使用ThreadLocal实现Java嵌套事务
public void rollback()
[转]POJO中使用ThreadLocal实现Java嵌套事务

回滚当前的事务,之后关闭连接,并将其从栈中移除。

上面的TransactionManagerStackImpl类为单线程创建了嵌套事务。

多线程的嵌套事务

在多线程的应用中,每个线程都有其独立的事务和嵌套事务。

我们使用ThreadLocal管理栈的连接。

[转]POJO中使用ThreadLocal实现Java嵌套事务
 1 importjava.sql.Connection;
 2  
 3 public class TransactionManagerThreadLocalimplementsTransactionManager {
 4      
 5     private static final ThreadLocal<TransactionManager>tranManager = newThreadLocal<TransactionManager>() {
 6          
 7     protected TransactionManager initialValue() {
 8         System.out.println(this.toString() + "--Thread Local Initialize--");
 9     return new TransactionManagerStackImpl();
10         }
11       };
12  
13     @Override
14     public void beginTransaction() {
15         tranManager.get().beginTransaction();
16     }
17  
18     @Override
19     public void commit() {
20         tranManager.get().commit();
21     }
22  
23     @Override
24     public void rollback() {
25         tranManager.get().rollback();
26     }
27  
28     @Override
29     public Connection getConnection() {
30         returntranManager.get().getConnection();
31     }
32 }
[转]POJO中使用ThreadLocal实现Java嵌套事务

这里初始化TransactionManagerStackImpl,在线程中创建嵌套的事务。

测试

测试上面的方法,提交内层事务,回滚外层事务。

[转]POJO中使用ThreadLocal实现Java嵌套事务
 1 importjava.sql.Connection;
 2  
 3 public class NestedMain implements Runnable {
 4      
 5     private int v = 0;
 6     private String name;
 7      
 8     NestedMain(int v, String name) {
 9         this.v = v;
10         this.name = name;
11     }
12  
13     public static void main(String[] args) throws Exception{
14          
15         for (inti = 0; i< 3; i++) {
16             NestedMain main = newNestedMain(i * 10, "Ravi" + i);
17             new Thread(main).start();
18         }
19     }
20  
21     @Override
22     public void run() {
23          
24         try {
25             TransactionManagerThreadLocal local = new TransactionManagerThreadLocal();
26              
27             // Transaction 1 ( outer )
28             local.beginTransaction();
29             Connection con = local.getConnection();
30             String sql = "INSERT INTO test_tran (emp_id, name) VALUES (‘1"+v+"‘, ‘"+ name+v+"‘)";
31             this.insert(con, sql);
32      
33                 // Transaction 2 ( Inner )
34                 local.beginTransaction();
35                 con = local.getConnection();
36                 sql = "INSERT INTO test_tran (emp_id, name) VALUES (‘2"+v+"‘, ‘"+ name+v+"‘)";
37                 this.insert(con, sql);
38                 local.commit(); // Committing 2
39  
40             local.rollback(); // Rollback 1 Outer
41  
42         } catch (Exception e) {
43             e.printStackTrace();
44         }
[转]POJO中使用ThreadLocal实现Java嵌套事务

结果

[转]POJO中使用ThreadLocal实现Java嵌套事务
com.ttit.TransactionManagerThreadLocal$1@1270b73--Thread Local Initialize--
com.ttit.TransactionManagerThreadLocal$1@1270b73--Thread Local Initialize--
com.ttit.TransactionManagerThreadLocal$1@1270b73--Thread Local Initialize--
com.mysql.jdbc.JDBC4Connection@10dd1f7--Conection---
com.mysql.jdbc.JDBC4Connection@1813fac--Conection---
com.mysql.jdbc.JDBC4Connection@136228--Conection---
com.mysql.jdbc.JDBC4Connection@1855af5--Conection---
com.mysql.jdbc.JDBC4Connection@e39a3e--Conection---
com.mysql.jdbc.JDBC4Connection@1855af5--Commit---
com.mysql.jdbc.JDBC4Connection@e39a3e--Commit---
com.mysql.jdbc.JDBC4Connection@9fbe93--Conection---
com.mysql.jdbc.JDBC4Connection@9fbe93--Commit---
com.mysql.jdbc.JDBC4Connection@10dd1f7--Rollback---
com.mysql.jdbc.JDBC4Connection@1813fac--Rollback---
com.mysql.jdbc.JDBC4Connection@136228--Rollback---
 
|  name       | emp_id           
| ------------- |:-------------:
| Ravi220        | 220
| Ravi00      | 20      
|Ravi110 | 210      
[转]POJO中使用ThreadLocal实现Java嵌套事务

内层事务回滚,外层事务提交的情况:

[转]POJO中使用ThreadLocal实现Java嵌套事务
com.ttit.TransactionManagerThreadLocal$1@1270b73--Thread Local Initialize--
com.ttit.TransactionManagerThreadLocal$1@1270b73--Thread Local Initialize--
com.ttit.TransactionManagerThreadLocal$1@1270b73--Thread Local Initialize--
com.mysql.jdbc.JDBC4Connection@9f2a0b--Conection---
com.mysql.jdbc.JDBC4Connection@136228--Conection---
com.mysql.jdbc.JDBC4Connection@1c672d0--Conection---
com.mysql.jdbc.JDBC4Connection@9fbe93--Conection---
com.mysql.jdbc.JDBC4Connection@1858610--Conection---
com.mysql.jdbc.JDBC4Connection@9fbe93--Rollback---
com.mysql.jdbc.JDBC4Connection@1858610--Rollback---
com.mysql.jdbc.JDBC4Connection@1a5ab41--Conection---
com.mysql.jdbc.JDBC4Connection@1a5ab41--Rollback---
com.mysql.jdbc.JDBC4Connection@9f2a0b--Commit---
com.mysql.jdbc.JDBC4Connection@136228--Commit---
com.mysql.jdbc.JDBC4Connection@1c672d0--Commit---
...
|  name       | emp_id           
| ------------- |:-------------:
| Ravi00         | 10
| Ravi220      | 120     
|Ravi110 | 110
[转]POJO中使用ThreadLocal实现Java嵌套事务

原文链接: javacodegeeks 翻译: ImportNew.com 人晓
译文链接: http://www.importnew.com/11049.html

[转]POJO中使用ThreadLocal实现Java嵌套事务,布布扣,bubuko.com

[转]POJO中使用ThreadLocal实现Java嵌套事务

上一篇:巧用javascript数组实现数据结构-堆栈与队列


下一篇:【Java】 重学Java的一些笔记