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

了解嵌套事务

事务可以嵌套在另一个内部。 因此,内部事务或外部事务可以回滚或提交,而不会影响其他事务。

创建新事务后,它将进入外部事务。 一旦内部事务以提交或回滚的方式完成,外部事务就可以执行提交或回滚而与内部事务无关。 首先关闭最里面的事务,然后继续进行最外面的事务。

使用简单POJO实施

创建界面如下:

importjava.sql.Connection;publicinterfaceTransactionManager {Connection getConnection();voidbeginTransaction();void commit();void rollback();
}

创建事务管理器类,如下所示:

importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.SQLException;
importjava.util.Stack;publicclassTransactionManagerStackImplimplementsTransactionManager {private Stack<Connection>connections = new Stack<Connection>();@Overridepublic Connection getConnection() {if (connections.isEmpty()) {this.addConn();}returnconnections.peek();}@OverridepublicvoidbeginTransaction() {this.addConn();}@Overridepublicvoid 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();}}@Overridepublicvoid 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();}}privatevoidaddConn() {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() {returngetConnection("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);returnDriverManager.getConnection(connection, user, password);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}returnnull;}
}

在这里,我们创建了一个堆栈:

private Stack<Connection> connections = new Stack<Connection>();

由于事务创建为LIFO(堆栈),因此我们使用了Java API中的Stack来维护每个事务的连接:

public void beginTransaction()

开始事务以开始新的事务并将连接添加到堆栈。 AutoCommit已设置为false:

public Connection getConnection()

获取当前事务的连接。 如果不存在,它将创建并添加到堆栈中:

public void commit()

提交当前事务并关闭连接,该连接也已从堆栈中删除:

public void rollback()

回滚当前事务并关闭连接,该连接也已从堆栈中删除。

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

多线程的嵌套事务

对于多线程应用程序,每个线程都有独立的事务和嵌套事务。

我们提出使用ThreadLocal来管理连接栈。

importjava.sql.Connection;publicclassTransactionManagerThreadLocalimplementsTransactionManager {privatestaticfinalThreadLocal<TransactionManager>tranManager = newThreadLocal<TransactionManager>() {protectedTransactionManagerinitialValue() {System.out.println(this.toString() + "--Thread Local Initialize--");returnnewTransactionManagerStackImpl();}};@OverridepublicvoidbeginTransaction() {tranManager.get().beginTransaction();}@Overridepublicvoid commit() {tranManager.get().commit();}@Overridepublicvoid rollback() {tranManager.get().rollback();}@Overridepublic Connection getConnection() {returntranManager.get().getConnection();}
}

在这里,我们初始化TransactionManagerStackImpl以在线程内部创建嵌套事务。

测试中

为了进行上述测试,请提交内部事务并回滚外部事务。

importjava.sql.Connection;publicclassNestedMainimplements Runnable {privateintv = 0;private String name;NestedMain(int v, String name) {this.v = v;this.name = name;}publicstaticvoid main(String[] args) throws Exception{for (inti = 0; i< 3; i++) {NestedMain main = newNestedMain(i * 10, "Ravi" + i);new Thread(main).start();}}@Overridepublicvoid run() {try {TransactionManagerThreadLocal local = newTransactionManagerThreadLocal();// 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 2local.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---
名称 emp_id
拉维220 220
拉维00 20
拉维110 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---
名称 emp_id
拉维00 10
拉维220 120
拉维110 110

资源:

  • 了解ThreadLocal背后的概念

翻译自: https://www.javacodegeeks.com/2013/12/java-nested-transaction-using-threadlocal-in-pojo.html

在POJO中使用ThreadLocal的Java嵌套事务相关推荐

  1. java pojo使用_在POJO中使用ThreadLocal进行Java嵌套事务

    java pojo使用 大多数嵌套事务是使用EJB实现的,现在我们尝试在POJO上实现嵌套事务. 在这里,我们使用了ThreadLocal的功能. 了解嵌套事务 事务可以嵌套在另一个内部. 因此,内部 ...

  2. POJO中使用ThreadLocal实现Java嵌套事务

    2019独角兽企业重金招聘Python工程师标准>>> 大多嵌套事务都是通过EJB实现的,现在我们尝试实现对POJO的嵌套事务.这里我们使用了ThreadLocal的功能. 理解嵌套 ...

  3. Java Review - 线程池中使用ThreadLocal不当导致的内存泄漏案例源码分析

    文章目录 概述 Why 内存泄露 ? 在线程池中使用ThreadLocal导致的内存泄漏 概述 ThreadLocal的基本使用我们就不赘述了,可以参考 每日一博 - ThreadLocal VS I ...

  4. Java中的ThreadLocal详解

    一.ThreadLocal简介 多线程访问同一个共享变量的时候容易出现并发问题,特别是多个线程对一个变量进行写入的时候,为了保证线程安全,一般使用者在访问共享变量的时候需要进行额外的同步措施才能保证线 ...

  5. Java多线程中的ThreadLocal,可继承,可修改

    Java多线程中的ThreadLocal,可继承,可修改. package test;import java.util.Date;public class InheritableThreadLocal ...

  6. Java中的ThreadLocal的使用--学习笔记

    ThreadLocal直译为"线程本地"或"本地线程",如果你真的这么认为,那就错了!其实它就是一个容器,用于存放线程的局部变量,我认为应该叫做ThreadLo ...

  7. 4问教你搞定java中的ThreadLocal

    摘要:ThreadLocal是除了加锁同步方式之外的一种保证规避多线程访问出现线程不安全的方法. 本文分享自华为云社区<4问搞定java中的ThreadLocal>,作者:breakDra ...

  8. threadlocal线程_线程故事:Web应用程序中的ThreadLocal

    threadlocal线程 本周,我花了一些合理的时间来消除Web应用程序中的所有ThreadLocal变量. 原因是他们造成了类加载器泄漏,我们不能再适当地取消部署我们的应用程序. 取消部署应用程序 ...

  9. 线程故事:Web应用程序中的ThreadLocal

    本周,我花了一些合理的时间来消除Web应用程序中的所有ThreadLocal变量. 原因是他们造成了类加载器泄漏,我们不能再适当地取消部署我们的应用程序. 取消部署应用程序后,当GC根目录继续引用应用 ...

最新文章

  1. 年轻,误把unix当linux
  2. INT_MAX和INT_MIN注意事项
  3. MyBatis基本运行环境
  4. 在线抠图工具:亲测有效
  5. 脚本可以放在html外,关于把script脚本放在html结束标签外的运行结果???
  6. 数据库考研SQL操作
  7. /etc/init.d/functions详解
  8. C# 获取UTC 转换时间戳为C#时间
  9. android x86 联网,没有网络连接 – VMWare Fusion上的Android-x86
  10. 最新抖音视频无水印解析接口及原理
  11. 计算机网络---网络编程套接字(二)
  12. Spectrum采集卡在飞行时间质谱中的应用案例
  13. 文件上传2-搭建uploads靶场
  14. gwt执行ajax,使用GWT开发AJAX应用程序
  15. deepin 相关问题
  16. Vue3生命周期及事件写法
  17. [Kerberos基础]-- kdc集群主从搭建(kerberos相关)
  18. JMS(Java消息服务)(Activemq简单介绍)
  19. uni-app 微信支付
  20. 关于推荐系统中的DOA

热门文章

  1. Android软键盘弹出时,覆盖布局,不是把布局顶上去的解决方法
  2. oracle8修改最大连接数,ORACLE查看并修改最大连接数的具体步骤
  3. matlab 的excel 对象,MATLAB 中的 COM 对象
  4. android查看wifi是否双频,Android判断wifi是5G还是2.4G
  5. java restful接口开发实例_实战:基于Spring Boot快速开发RESTful风格API接口
  6. asp 执行 exe_EXE程序加密锁下载-EXE程序加密锁电脑版下载v5.0
  7. java初学者指南_Java代理初学者指南
  8. java中抽象类继承抽象类_用Java中的抽象类扩展抽象类
  9. log4j2 xsd_Log4j 2.x XSD的描述不完整
  10. 装饰着模式示例_装饰器设计模式示例