解决spring多线程不共享事务的问题
在一个事务中使用多线程操作数据库时,若同时存在对数据库的读写操作,可能出现数据读取的不准确,因为多线程将不会共享同一个事务(也就是说子线程和主线程的事务不一样),为了解决这个问题,可以使用spring的分布式事务jta,并重写JtaTransactionManager的doCommit和doRollback方法。
1、引入maven依赖
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jdbc</artifactId>
<version>3.9.3</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
2、配置xml文件
<!-- atomikos事务管理器 -->
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<description>UserTransactionManager</description>
<property name="forceShutdown">
<value>true</value>
</property>
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="3000" />
</bean>
<!-- spring 事务管理器,必须使用二次开发的类,控制solr的回滚 -->
<bean id="springTransactionManager"
class="com.yzh.core.inner.impl.SepJtaTransactionManager">
<property name="transactionManager">
<ref bean="atomikosTransactionManager" />
</property>
<property name="userTransaction">
<ref bean="atomikosUserTransaction" />
</property>
<!-- 必须设置,否则程序出现异常 JtaTransactionManager does not support custom isolation levels by default -->
<property name="allowCustomIsolationLevels" value="true"/>
</bean>
<!-- 开启注解事务定义,由Spring扫描注解定义的事务 -->
<tx:annotation-driven transaction-manager="springTransactionManager" proxy-target-class="true" />
3、将一些查询数据库的操作放到容器里面,在事务提交的时候执行
public class ContextKeeper {
private static final ThreadLocal<Collection<Runnable>> keepAfterSubmit = new ThreadLocal<>();
//将需要执行的多线程放到容器中
public static void put(Collection<Runnable> tasks) {
keepAfterSubmit.set(tasks);
} //获取并移除容器中的任务
public static Collection<Runnable> getAndRemoveSubmitTask() {
synchronized (keepAfterSubmit) {
Collection<Runnable> tasks = keepAfterSubmit.get();
keepAfterSubmit.remove();
return tasks;
}
}
//移除容器中的任务
public static void removeSubmitTask() {
synchronized (keepAfterSubmit) {
keepAfterSubmit.remove();
}
}
4、重写JtaTransactionManager的doCommit和doRollback方法。
public class SepJtaTransactionManager extends JtaTransactionManager {
/**
*
*/
private static final long serialVersionUID = -1468472287996669189L;
private static final Logger LOGGER = LoggerDeputyUtil.getSelfClassLogger();
@Override
protected void doCommit(DefaultTransactionStatus status) {
super.doCommit(status);// 执行后续任务
Collection<Runnable> tasks = ContextKeeper.getAndRemoveSubmitTask();
if (!JudgeUtil.isEmpty(tasks)) {
LOGGER.info("执行后续任务");
try {
ExecutorService pool = CommonHelper.pool();
for (Runnable task : tasks) {
pool.submit(task);
}
} catch (Exception e) {
ErrorLevel.LOG_HANDLERHIS_FAIL.doLog("执行后续任务失败", e);
}
}
}
@Override
protected void doRollback(DefaultTransactionStatus status) {
super.doRollback(status);// 清空任务
ContextKeeper.removeSubmitTask();
}
}
解决spring多线程不共享事务的问题的更多相关文章
- spring 多线程 注入 服务层 问题
在用多线程的时候,里面要用到Spring注入服务层,或者是逻辑层的时候,一般是注入不进去的.具体原因应该是线程启动时没有用到Spring实例不池.所以注入的变量值都为null. 详细:http://h ...
- spring中注解式事务不生效的问题
常用的解决方法可以百度,我针对我的问题描述一下 Mysql中InnoDB引擎才支持事务, MyISAM不支持事务. 当你尝试了各种方法解决spring中注解式事务不生效时, 一定要查看一下数据库中表的 ...
- Spring单实例、多线程安全、事务解析
原文:http://blog.csdn.net/c289054531/article/details/9196053 引言: 在使用Spring时,很多人可能对Spring中为什么DAO和Se ...
- spring学习 8-面试(事务,解决线程安全)
1.介绍一下Spring的事物管理 参考:Spring 学习7 -事务 2.Spring如何处理线程并发问题 Spring使用ThreadLocal解决线程安全问题 参考:Spring学习11- ...
- Spring笔记(4) - Spring的编程式事务和声明式事务详解
一.背景 事务管理对于企业应用而言至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性.就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作 ...
- 全面分析 Spring 的编程式事务管理及声明式事务管理
开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本 ...
- JAVA多线程之间共享数据BlockingQueue介绍
在JAVA的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题.通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利. ...
- 解决spring配置中的bean类型的问题:BeanNotOfRequiredTypeException
解决spring配置中的bean类型的问题:BeanNotOfRequiredTypeException这个问题出现的原因:一般在使用annotation的方式注入spring的bean 出现的,具体 ...
- spring的annotation-driven配置事务管理器详解
http://blog.sina.com.cn/s/blog_8f61307b0100ynfb.html ——————————————————————————————————————————————— ...
随机推荐
- mybatis error
2018-08-02 14:01:18.021 WARN org.apache.catalina.loader.WebappClassLoaderBase Line:179 - The web app ...
- 004_centos安装pip的几种方式及pip源
一. (1) yum -y install epel-release yum install python-pip pip install --upgrade pip (2) python脚本的一键安 ...
- Python2 处理 Unicode 字符串的规则
在 Python2 中处理 Unicode 字符串,需遵循如下规则: 1. 程序中的字符串要加前缀 u 2. 不要用 str(),而应该用 unicode() 作为字符串转换函数.不要使用 chr() ...
- Spring Security(六):2.3 Release Numbering
It is useful to understand how Spring Security release numbers work, as it will help you identify th ...
- CF1083E The Fair Nut and Rectangles
CF1083E The Fair Nut and Rectangles 给定 \(n\) 个平面直角坐标系中左下角为坐标原点,右上角为 \((x_i,\ y_i)\) 的互不包含的矩形,每一个矩形拥有 ...
- 工具篇-Json处理
1. @JsonProperty和@SerializedName注解 使用场景 将一个json格式的字符串转换成某个java对象,或者将一个java对象转换成json格式的字符串时,如果json字符串 ...
- mongo索引命令
http://blog.csdn.net/salmonellavaccine/article/details/53907535 1. 创建/重建索引 MongoDB全新创建索引使用ensureInde ...
- 【php增删改查实例】第二十五节 - 在main.php中显示头像
在用户成功上传头像以后,用户登录系统,应该能够看到自己的头像,本节演示如何在这个地方: 添加用户头像. 1.用DIV做: border-radius:50% background:url(xxx.jp ...
- xampp 使用过程中刚遇到的问题记录
开始使用XAMPP的时候,都是可以正常连接的,但是过一段时间后,在用它创建表或其他操作,会报错,提示如下错误 Access denied for user ''@'localhost' to data ...
- 了解可执行的NPM包
NPM是Node.js的包管理工具,随着Node.js的出现,以及前端开发开始使用gulp.webpack.rollup以及其他各种优秀的编译打包工具(大多数采用Node.js来实现),大家都开始接触 ...