在POJO中使用ThreadLocal的Java嵌套事务

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

了解嵌套事务

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

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

图片1

使用简单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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/365514.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML存储详解

和大家一起先来了解一下H5之前的存储方式&#xff1a; cookies的诞生&#xff1a; http请求头上带着数据大小只能为4K主Domain的污染 下面是百度的一些Cookies HTTP中带√的表示&#xff0c;只能被服务器端修改的数据&#xff0c;一般用来存储身份验证等信息 cookies造成了…

java 导入excel到数据库_java导入excel到数据库

1.[文件] jxl-2.6.jar ~ 645KB 下载(124)2.[代码]将excel表格内容解析为listpackage com.utils;import java.io.File;import java.util.ArrayList;import java.util.List;import jxl.Sheet;import jxl.Workbook;import com.jiumai.shgold.model.aboutas.AboutAs;public cla…

智课雅思词汇---十六、前缀hyper和hypo是反义词

智课雅思词汇---十六、前缀hyper和hypo是反义词 一、总结 一句话总结&#xff1a; hypertension 过度紧张&#xff1b;高血压&#xff08;hypertension紧张&#xff09; hypotension 低血压 1、epi是什么意思&#xff1f; 前缀&#xff1a;ep-, epi-, eph- 【词根含义】&#x…

python神经网络库 keras_在Python和R中使用Keras和Tensorflow进行深度学习

了解TensorFlow 2.0和Keras在Python和R中的深度学习并构建神经网络深入了解人工神经网络(ANN)和深度学习了解Keras和Tensorflow库的用法了解适用人工神经网络(ANN)的业务场景使用Python和R构建人工神经网络(ANN)使用人工神经网络(ANN)进行预测完成本课程后&#xff0c;您将能够…

springboot 工程启动报错之Consider defining a bean of type ‘XXX’ in your configuration.

一、前言&#xff1a; 使用springboot自动注入的方式搭建好了工程&#xff0c;结果启动的时候报错了&#xff01;&#xff01;&#xff01;&#xff0c;错误如下图&#xff1a; Description:Field userEntityMapper in com.xxx.xxx.service.UserService required a bean of typ…

结合使用嵌入式Tomcat和Maven tomcat插件

使用Eclipse WTP开发Java Web应用程序时&#xff0c;我们需要在计算机中安装tomcat才能执行该应用程序。 如果在项目上使用Maven&#xff0c;则可以使用tomcat插件运行嵌入式tomcat安装并测试应用程序。 如下所示&#xff0c;这非常简单。 OBS&#xff1a;要执行本文中给出的…

java 自定义报表_灵活数据分析 | 自定义数据分析_集力数据系统平台_Java报表系统软件...

灵活数据分析集力数据系统数据分析是立足于让终端用户即使不懂专业计算机技术也能即时定义报表和分析数据的工具。用户只需关心业务需要&#xff0c;无需关心技术实现&#xff0c;通过拖拖拽拽、点点选选即可轻松制作列表式报表、分组报表、交叉报表、自由报表、组合报表等并进…

洛谷 P4878 [USACO05DEC]layout布局

题面链接 sol&#xff1a;差分约束系统裸题&#xff0c;根据ab<c建个图跑个最短路就没了。。。 #include <queue> #include <cstdio> #include <cstring> #include <iostream> using namespace std; #define int long long #define M(a,v) memset(a…

(1-1)line-height的定义和行内框盒子模型

&#xff08;1-1&#xff09;line-height的定义和与行内框盒子模型的关系 一、line-height的定义 line-height的定义&#xff1a; 行高&#xff0c;又称为两基线的距离。默认基线对齐&#xff08;因为CSS所有*线&#xff1a;总之就是各种定义的线都是和基线对齐的&#xff09…

PHP的命名空间

1.什么是命名空间&#xff0c;官方文档定义为&#xff1a; 什么是命名空间&#xff1f;从广义上来说&#xff0c;命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。例如&#xff0c;在操作系统中目录用来将相关文件分组&#xff0c;对于目录中的文件来说&…

Java与本机代理–他们所做的强大功能

在安装代理之前应了解的内容以及它如何影响您的代码 在构建可伸缩的服务器端应用程序时&#xff0c;我们花费大量时间思考如何在生产中监视&#xff0c;操作和更新代码。 已经开发出一种新的工具来帮助Java和Scala开发人员做到这一点。 它们中的许多都是基于最强大的方法之一构…

pdf打印机安装程序_CAD快速出打印PDF格式文件

pdf最大的特点就是只能查看&#xff0c;不可编辑。我们肯定不能够直接给到客户CAD源文件&#xff0c;所以我们需要把CAD文件格式&#xff0c;转换成为PDF格式。PDF格式&#xff0c;比起CAD文件&#xff0c;能够更好的阅览CAD是不能够直接生成PDF格式的&#xff0c;所以我们需要…

javascript(1)

js是ajax/jquery/extjs的基础。 js的应用&#xff0c;比如百度地图网页版&#xff0c;用鼠标拖拽画面&#xff0c;然后画面会刷新&#xff0c;这就是用js实现的。 只要涉及到鼠标的响应&#xff0c;按键的响应都和js有关。 写网页版地图需要调用谷歌的api。 JavaScript所讲内容…

如何将html特殊字符编码转换成特殊字符_html十进制编码字符转回来

备注&#xff1a;有时候我们会莫名其妙遇到一些特殊字符&#xff1a; 这些字符在网页上能正常显示&#xff0c;但是在APP特殊情景并不识别这些字符&#xff1a; 如&#xff1a; 这个其实是单引号: 百度后发现&#xff0c;它其实是HTML特殊字符的十进制编码&#…

JavaScript之预编译

JavaScript执行步骤 1.检查通篇的语法错误2.预编译过程3.解释一行&#xff0c;执行一行 1 (a)2 test()3 function test() {4 console.log(1) // 15 }6 7 (b)8 console.log(a); // undefined9 var a ; 10 11 函数申明整体提升&#xff0c;变量只有申明提升…

使Netty 4中的HTTP内容压缩工作

Netty确实是一个很棒的框架&#xff0c;提供了构建高性能HTTP服务器所需的所有功能。 令人高兴的是&#xff0c;几乎所有东西都是开箱即用的&#xff0c;只是必须以正确的方式组合在一起。 内容压缩 &#xff08;gzip或deflate&#xff09;也不例外。 但是&#xff0c;在压缩静…

sap生产工单报工_【案例】MES系统助力亨通电缆车间生产效率提升25%

一、企业简介江苏亨通电力电缆有限公司是亨通集团旗下的一家重点高新技术企业&#xff0c;于2003年在上交所成功上市&#xff0c;属于上市公司的电力传输板块。公司目前已拥有超高压电力电缆、超高压海缆、中低压电力电缆、电气装备用电缆、特高压导线、电力光缆以及铜铝加工等…

mysql 二叉树表设计_mysql---B+tree索引的设计原理

1.什么是数据库的索引每种查找算法都只能应用于特定的数据结构之上&#xff0c;例如二分查找要求被检索数据有序&#xff0c;而二叉树查找只能应用于二叉查找树上&#xff0c;但是数据本身的组织结构不可能完全满足各种数据结构(例如&#xff0c;理论上不可能同时将两列都按顺序…

JS_单个或多个文件上传_不支持单独修改

A-From表单直接填写提交地址&#xff0c;不过干预&#xff1a; 1. 单文件上传 最简单的文件上传&#xff0c;是单文件上传&#xff0c;form标签中加入enctype"multipart/form-data"&#xff0c;form表单中有一个input[type"file"]项 <form name"…

一些算法学习的推荐博文阅读(数论居多,图论没有)

上面是自己的学习笔记&#xff0c;下面是推荐博文阅读 关于每个知识点的阅读顺序若不加序号一般是并列的&#xff0c;有序号的话一般是推荐看&#xff08;当然一知半解的话可以从头看起也可以从中间开始&#xff09; 另外&#xff0c;有的链接放在推荐的下面了 另另外&#xff…