博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJO中使用ThreadLocal实现Java嵌套事务
阅读量:6576 次
发布时间:2019-06-24

本文共 7183 字,大约阅读时间需要 23 分钟。

hot3.png

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

理解嵌套事务

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

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

使用简单的POJO实现

新建如下接口:

importjava.sql.Connection; public interface TransactionManager {     Connection getConnection();    void beginTransaction();    void commit();    void rollback();}

新建如下事务管理类:

importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.SQLException;importjava.util.Stack; public class TransactionManagerStackImpl implements TransactionManager {         private Stack
connections = new Stack
();     @Override    public Connection getConnection() {         if (connections.isEmpty()) {            this.addConn();        }         return connections.peek();    }     @Override    public void beginTransaction() {        this.addConn();    }     @Override    public void commit() {        try {            if (connections.peek() != null&& !connections.peek().isClosed()) {                System.out.println(connections.peek().toString() +"--Commit---");                connections.peek().commit();                connections.pop().close();            }         } catch (SQLException e) {            e.printStackTrace();        }     }     @Override    public void rollback() {        try {             if (connections.peek() != null&& !connections.peek().isClosed()) {                System.out.println(connections.peek().toString() +"--Rollback---");                connections.peek().rollback();                connections.pop().close();            }        } catch (SQLException e) {            e.printStackTrace();        }     }     private void addConn() {        try {            Connection con = this.getMysqlConnection();            con.setAutoCommit(false);            connections.push(con);            System.out.println(con.toString() +"--Conection---");        } catch (SQLException e) {            e.printStackTrace();        }             }     private Connection getMysqlConnection() {        return getConnection("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/testdb", "test", "test12345");    }     private Connection getConnection(String driver, String connection,            String user, String password) {         try {            Class.forName(driver);            return DriverManager.getConnection(connection, user, password);        } catch (ClassNotFoundException e) {            e.printStackTrace();        } catch (SQLException e) {            e.printStackTrace();        }         returnnull;     }}

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

private Stack
 connections = new Stack
();

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

public void beginTransaction()

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

public Connection getConnection()

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

public void commit()

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

public void rollback()

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

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

多线程的嵌套事务

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

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

importjava.sql.Connection; public class TransactionManagerThreadLocalimplementsTransactionManager {         private static final ThreadLocal
tranManager = newThreadLocal
() {             protected TransactionManager initialValue() {        System.out.println(this.toString() + "--Thread Local Initialize--");    return new TransactionManagerStackImpl();        }      };     @Override    public void beginTransaction() {        tranManager.get().beginTransaction();    }     @Override    public void commit() {        tranManager.get().commit();    }     @Override    public void rollback() {        tranManager.get().rollback();    }     @Override    public Connection getConnection() {        returntranManager.get().getConnection();    }}

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

测试

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

importjava.sql.Connection; public class NestedMain implements Runnable {         private int v = 0;    private String name;         NestedMain(int v, String name) {        this.v = v;        this.name = name;    }     public static void main(String[] args) throws Exception{                 for (inti = 0; i< 3; i++) {            NestedMain main = newNestedMain(i * 10, "Ravi" + i);            new Thread(main).start();        }    }     @Override    public void run() {                 try {            TransactionManagerThreadLocal local = new TransactionManagerThreadLocal();                         // Transaction 1 ( outer )            local.beginTransaction();            Connection con = local.getConnection();            String sql = "INSERT INTO test_tran (emp_id, name) VALUES ('1"+v+"', '"+ name+v+"')";            this.insert(con, sql);                     // Transaction 2 ( Inner )                local.beginTransaction();                con = local.getConnection();                sql = "INSERT INTO test_tran (emp_id, name) VALUES ('2"+v+"', '"+ name+v+"')";                this.insert(con, sql);                local.commit(); // Committing 2             local.rollback(); // Rollback 1 Outer         } catch (Exception e) {            e.printStackTrace();        }

结果

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

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

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

转载于:https://my.oschina.net/ydsakyclguozi/blog/392991

你可能感兴趣的文章
HDU1164 Eddy's research I(解法二)
查看>>
UVA11192 Group Reverse
查看>>
UVA10603 Fill
查看>>
fwt模板
查看>>
立即执行函数: (function(){...})() 与 (function(){...}()) 有什么区别?
查看>>
sth else special(json distribution)
查看>>
如何让 height:100%; 起作用
查看>>
Java中list在循环中删除元素的坑
查看>>
[转]100个常用的linux命令
查看>>
cocos creator destroy方法
查看>>
第二课 HTML+CSS
查看>>
time random sys os模块
查看>>
第一章 台达组态软件的基本介绍
查看>>
DOM_04之常用对象及BOM
查看>>
LOJ#2085 循环之美
查看>>
Leetcode | Longest Common Prefix
查看>>
Filter实现用户自动登录
查看>>
第十九天笔记
查看>>
发送json给服务器
查看>>
日历控件datetimepicker(IE11)
查看>>