解决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 ——————————————————————————————————————————————— ...
随机推荐
- DVR登录绕过漏洞(CVE-2018-9995)
###漏洞描述 此漏洞允许攻击者通过修改“Cookie: uid=admin” 之后访问特定 DVR 的控制面板,返回此设备的明文管理员凭证. ###漏洞利用 1.利用代码 curl "ht ...
- flask_sqlalchemy中根据聚合分组后的结果进行排序,根据日期(datetime)按天分组
from sqlalchemy import func, desc # 根据聚合查询总收入,按总收入逆序 s= db.session.query(TpOrders.room_type_id, (fun ...
- ScriptManager的几个属性和方法
ScriptManager的几个属性和方法 一.EnablePageMethods ScriptManager的EnablePageMethods属性用于设定客户端javascript直接调用服务 ...
- 小技巧:改变 VS Code 工作区页面背景
效果图: 步骤(一): 1.点击页面左上角 文件/首选项/设置 2.在搜索框中输入:background 如下图. 3.找到 Background: Custom Images 选项并点击在 ...
- vsftpd 有关vsftpd的3个注意事项。。sshd[pid]: fatal: chroot into directory without nodev and either noexec or nosuid
今天帮助已好友配置vsftpd,可能是长时间不用这个东西了,竟然这里个半天才把需求折腾完, 其实需求简单,就是使用系统账户登录,不可跳转目录,限制权限,只能上次不能下载. 懵逼一: 最开始配置sftp ...
- Matconvnet笔记(一)
参考网址:http://www.vlfeat.org/matconvnet/ 内容参考博客:http://blog.sina.com.cn/s/blog_92cd3a1c0102x1ch.html M ...
- Jupyter notebook工具栏隐藏和jupyter notebook主题更改
有趣的事,Python永远不会缺席! 如需转发,请注明出处:小婷儿的python https://www.cnblogs.com/xxtalhr/p/10747200.html 一.问题 Jupyt ...
- LDAP2-创建OU创建用户
创建OU创建用户 1.创建OU 选择Organisational unit 组织单元 输入OU名称 提交信息 结果创建成功 2.创建员工 选择ou选择新建子条目 选择默认模板 选择inetorgper ...
- 深入理解[Master-Worker模式]原理与技术
Master-Worker模式是常用的并行模式之一.它的核心思想是,系统由两类进程协作工作:Master进程和Worker进程.Master进程负责接收和分配任务,Worker进程负责处理子任务.当各 ...
- ML.NET 示例:推荐之场感知分解机
写在前面 准备近期将微软的machinelearning-samples翻译成中文,水平有限,如有错漏,请大家多多指正. 如果有朋友对此感兴趣,可以加入我:https://github.com/fei ...