Spring+Hibernate+Atomikos集成构建JTA的分布式事务--解决多数据源跨库事务

一、概念

分布式事务
分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。简言之,同时操作多个数据库保持事务的统一,达到跨库事务的效果。

JTA
JTA,即Java Transaction API,JTA允许应用程序执行分布式事务处理———在两个或多个网络计算机资源上访问并且更新数据。JDBC驱动程序的JTA支持极大地增强了数据访问能力。

JTA和JTS

Java事务API(JTA:Java Transaction API)和它的同胞Java事务服务(JTS:Java Transaction Service),为J2EE平台提供了分布式事务服务(distributed transaction)。
一个分布式事务(distributed transaction)包括一个事务管理器(transaction manager)和一个或多个资源管理器(resource manager)。
一个资源管理器(resource manager)是任意类型的持久化数据存储。
事务管理器(transaction manager)承担着所有事务参与单元者的相互通讯的责任。

JTA与JDBC

JTA事务比JDBC事务更强大。一个JTA事务可以有多个参与者,而一个JDBC事务则被限定在一个单一的数据库连接。下列任一个Java平台的组件都可以参与到一个JTA事务中:JDBC连接、JDO PersistenceManager 对象、JMS 队列、JMS 主题、企业JavaBeans(EJB)、一个用J2EE Connector Architecture 规范编译的资源分配器。

JOTM
JOTM (Java Open Transaction Manager)是一个开源独立的事务管理器,支持分布式事务,Spring3.X已经不再支持JOTM

Atomikos
Atomikos TransactionsEssentials是一个为Java平台提供增值服务的并且开源类事务管理器,支持分布式事务,本文所采用的技术。

Atomikos是目前在分布式事务管理中做得相当不错的开源软件。有10年以上的经验,Atomikos保障您的关键事务和防止昂贵的数据丢失在发生系统故障或事故中.Atomikos支持XA(全局事务)和NON-XA(非全局事务),NON-XA效率高于XA。本文主要是讲XA事件,因为要在不同的数据库中操作多张表。

接下来说一下spring.x+hibernate中集成Atomikos构建JTA的分布式事务

二、Spring.x+Hibernate+Atomikos集成
Spring.x+Hibernate怎么集成此处省略不说,主要讲解Spring.x+Atomikos的集成,操作步骤如下:

1、下载Atomikos,需要以下这些包

atomikos-util-1.0.jar
cglib-nodep-2.2.2.jar
transactions-3.7.0.jar
transactions-api-3.7.0.jar
transactions-jdbc-3.7.0.jar
transactions-jta-3.7.0.jar

2、配置
在applicationContext.xml文件当中作如下配置

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:jaxws="http://cxf.apache.org/jaxws"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsdhttp://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"><context:annotation-config /><!-- 通过注解方式自动扫描需交给sping管理的Bean --><context:component-scan base-package="com.ljq" /><!-- spring atomikos配置 --><!-- bpm数据源 --><bean id="bpmDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"><!-- Set unique name for this DataSource -->  <property name="uniqueResourceName"><value>bpm</value></property><!-- Set XADatasource class name-->  <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" /><property name="xaProperties"><props><prop key="user">root</prop><prop key="password">parami2013</prop><prop key="url">jdbc:mysql://192.168.1.254:3306/parami_bpm</prop></props></property><!-- set properties for datasource connection pool -->  <property name="poolSize" value="3" /><!-- 管理 Connection 被占用的时间 --><!-- 如果不设置这个值,Atomikos使用默认的300秒(即5分钟),那么在处理大批量数据读取的时候,一旦超过5分钟,就会抛出类似 Resultset is close 的错误 --><property name="reapTimeout"><value>20000</value></property>  </bean><!-- center数据源 --><bean id="centerDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"><property name="uniqueResourceName"><value>center</value></property><property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" /><property name="xaProperties"><props><prop key="user">root</prop><prop key="password">parami2013</prop><prop key="url">jdbc:mysql://192.168.1.254:3306/parami_center</prop></props></property><!-- 连接池里面连接的个数 --><property name="poolSize" value="3" /><!-- 管理 Connection 被占用的时间 --><!-- 如果不设置这个值,Atomikos使用默认的300秒(即5分钟),那么在处理大批量数据读取的时候,一旦超过5分钟,就会抛出类似 Resultset is close 的错误 --><property name="reapTimeout"><value>20000</value></property>  </bean><!-- 将hibernate数据源注入sessionFactory --><bean id="bpmSessionFactory"class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"><property name="dataSource" ref="bpmDataSource" /><property name="packagesToScan"><list><value>com.ljq.pojo</value></list></property><property name="hibernateProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop><prop key="hibernate.show_sql">true</prop><!-- 慎重(推荐禁止) 固定为update --><prop key="hibernate.hbm2ddl.auto">update</prop><prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</prop></props></property></bean><!-- 将hibernate数据源注入sessionFactory --><bean id="centerSessionFactory"class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"><property name="dataSource" ref="centerDataSource" /><property name="packagesToScan"><list><value>com.ljq.pojo</value></list></property><property name="hibernateProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop><prop key="hibernate.show_sql">true</prop><!-- 慎重(推荐禁止) 固定为update --><prop key="hibernate.hbm2ddl.auto">update</prop><prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</prop></props></property></bean>    <!-- atomikos事务管理器 --><bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"><property name="forceShutdown"><value>true</value></property></bean><bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"><property name="transactionTimeout" value="300" /></bean><!-- spring 事务管理器 --><bean id="springTransactionManager"class="org.springframework.transaction.jta.JtaTransactionManager"><property name="transactionManager" ref="atomikosTransactionManager"/><property name="userTransaction" ref="atomikosUserTransaction" /><property name="allowCustomIsolationLevels" value="true"/> </bean><!-- 使用annotation定义事务,对于要加入事物的类,只需对该类加 @Transactional  --><tx:annotation-driven transaction-manager="springTransactionManager" /><!-- hibernate Dao层模板 --><bean id="bpmHibernateTemplate"class="org.springframework.orm.hibernate3.HibernateTemplate"><property name="sessionFactory" ref="bpmSessionFactory"></property></bean><bean id="centerHibernateTemplate"class="org.springframework.orm.hibernate3.HibernateTemplate"><property name="sessionFactory" ref="centerSessionFactory"></property></bean></beans>
复制代码

3、在src文件夹下面加入一个transactions.properties文件

复制代码
# SAMPLE PROPERTIES FILE FOR THE TRANSACTION SERVICE
# THIS FILE ILLUSTRATES THE DIFFERENT SETTINGS FOR THE TRANSACTION MANAGER
# UNCOMMENT THE ASSIGNMENTS TO OVERRIDE DEFAULT VALUES;# Required: factory implementation class of the transaction core.
# NOTE: there is no default for this, so it MUST be specified! 
# 
com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory# Set base name of file where messages are output 
# (also known as the 'console file').
#
# com.atomikos.icatch.console_file_name = tm.out# Size limit (in bytes) for the console file;
# negative means unlimited.
#
# com.atomikos.icatch.console_file_limit=-1# For size-limited console files, this option
# specifies a number of rotating files to 
# maintain.
#
# com.atomikos.icatch.console_file_count=1# Set the number of log writes between checkpoints
#
# com.atomikos.icatch.checkpoint_interval=500# Set output directory where console file and other files are to be put
# make sure this directory exists!
#
# com.atomikos.icatch.output_dir = ./# Set directory of log files; make sure this directory exists!
#
# com.atomikos.icatch.log_base_dir = ./# Set base name of log file
# this name will be  used as the first part of 
# the system-generated log file name
#
# com.atomikos.icatch.log_base_name = tmlog# Set the max number of active local transactions 
# or -1 for unlimited.
#
# com.atomikos.icatch.max_actives = 50# Set the default timeout (in milliseconds) for local transactions
#
# com.atomikos.icatch.default_jta_timeout = 10000# Set the max timeout (in milliseconds) for local transactions
#
# com.atomikos.icatch.max_timeout = 300000# The globally unique name of this transaction manager process
# override this value with a globally unique name
#
# com.atomikos.icatch.tm_unique_name = tm# Do we want to use parallel subtransactions? JTA's default
# is NO for J2EE compatibility
#
# com.atomikos.icatch.serial_jta_transactions=true# If you want to do explicit resource registration then
# you need to set this value to false.
#
# com.atomikos.icatch.automatic_resource_registration=true  # Set this to WARN, INFO or DEBUG to control the granularity
# of output to the console file.
#
# com.atomikos.icatch.console_log_level=WARN# Do you want transaction logging to be enabled or not?
# If set to false, then no logging overhead will be done
# at the risk of losing data after restart or crash.
#
# com.atomikos.icatch.enable_logging=true# Should two-phase commit be done in (multi-)threaded mode or not?
# Set this to false if you want commits to be ordered according
# to the order in which resources are added to the transaction.
#
# NOTE: threads are reused on JDK 1.5 or higher. 
# For JDK 1.4, thread reuse is enabled as soon as the 
# concurrent backport is in the classpath - see 
# http://mirrors.ibiblio.org/pub/mirrors/maven2/backport-util-concurrent/backport-util-concurrent/
#
# com.atomikos.icatch.threaded_2pc=false# Should shutdown of the VM trigger shutdown of the transaction core too?
#
# com.atomikos.icatch.force_shutdown_on_vm_exit=false
复制代码

4、注入HibernateTemplate模板
a、为bpm库注入HibernateTemplate模板

复制代码
public abstract class BpmDaoSupport<T> extends DaoSupport<T> {protected HibernateTemplate bpmHibernateTemplate;/*** HibernateTemplate注入* * @param bpmHibernateTemplate*/@Resourcepublic void setBpmHibernateTemplate(HibernateTemplate bpmHibernateTemplate) {this.bpmHibernateTemplate = bpmHibernateTemplate;setHibernateTemplate(bpmHibernateTemplate);}}
复制代码

b、为center库注入HibernateTemplate模板

复制代码
public abstract class CenterDaoSupport<T> extends DaoSupport<T> {protected HibernateTemplate centerHibernateTemplate;/*** HibernateTemplate注入* * @param centerHibernateTemplate*/@Resourcepublic void setCenterHibernateTemplate(HibernateTemplate centerHibernateTemplate) {this.centerHibernateTemplate = centerHibernateTemplate;setHibernateTemplate(centerHibernateTemplate);}
}
复制代码

5、编写业务逻辑代码

复制代码
@Service(value="userServiceBean")
@Transactional
public class UserServiceBean implements UserService {@Resource(name="userDaoBean") private UserDao userDao;@Resource(name="userRoleDaoBean") private UserRoleDao userRoleDao;public List<User> queryUser() {return userDao.queryUser();}public void save(User user, UserRole ur) {userDao.save(user); //a处//此处报异常System.out.println(1/0); //b处
        ur.setUserId(user.getUid());userRoleDao.save(ur); //c处
    }
}
复制代码

在执行save()方法时会报java.lang.ArithmeticException: / by zero异常,b处的“1/0”有问题,因为除数不能为0;
如果事务生效,save()方法会回滚掉,即a处、c处不做save操作,保持事务的原子性;
如果事务不起作用,那么a处会执行成功,往数据库添加一条记录;b处抛出异常终止向下执行;c处这条代码不执行,导致脏数据的出现。

Atomikos的集成到此就结束了,亲!是不是很简单。

注意
MySQL的驱动需要5.1.10版本以上,低版本会出现如下错误:
java.lang.IllegalArgumentException: null source

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

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

相关文章

spring el表达式 if else_Spring 获取单例流程(二)

读完这篇文章你将会收获到Spring 中 prototype 类型的 bean 如何做循环依赖检测Spring 中 singleton 类型的 bean 如何做循环依赖检测前言继上一篇文章 Spring 获取单例流程(一) 我们这次继续往下分析一下后面的流程上一篇文章中我们说到&#xff0c;首先我们根据 name 找到其对…

Apache Spark RDD和Java流

几个月前&#xff0c;我很幸运地参加了一些使用Apache Spark的PoC&#xff08;概念验证&#xff09;。 在这里&#xff0c;我有机会使用弹性分布式数据集&#xff08;简称RDD &#xff09;&#xff0c;转换和操作。 几天后&#xff0c;我意识到虽然Apache Spark和JDK是非常不同…

用脚本js把结果转化为固定小数位的形式

function roundTo(base,precision) {var mMath.pow(10,precision);var aMath.round(base * m) / m;return a; } 例如&#xff1a;给定数字n6.3241712&#xff0c;则用roundTo&#xff08;n,0&#xff09;得4&#xff0c;用roundTo(n,7)得到6.3241712转载于:https://www.cnblogs…

存储过程详解

什么是存储过程&#xff1a;存储过程可以说是一个记录集吧&#xff0c;它是由一些T-SQL语句组成的代码块&#xff0c;这些T-SQL语句代码像一个方法一样实现一些功能&#xff08;对单表或多表的增删改查&#xff09;&#xff0c;然后再给这个代码块取一个名字&#xff0c;在用到…

gpu版tensorflow测试

测试程序&#xff1a; import tensorflow as tfwith tf.Session(configtf.ConfigProto(allow_soft_placementTrue, log_device_placementFalse)) as sess:a tf.constant(1)b tf.constant(3)c a bprint(结果是&#xff1a;%d\n 值为&#xff1a;%d % (sess.run(c), sess.ru…

随机森林原理_机器学习(29):随机森林调参实战(信用卡欺诈预测)

点击“机器学习研习社”&#xff0c;“置顶”公众号重磅干货&#xff0c;第一时间送达回复【大礼包】送你机器学习资料与笔记回顾推荐收藏>机器学习文章集合&#xff1a;1-20机器学习(21): Tensorflow Keras手写数字识别机器学习(22): Tensorflow Keras识别猫狗机器学习(23)…

sudo 命令报错的解决方法

尝试着用终端打开Mac的安全权限&#xff08;sudo spctl --master-disable&#xff09;&#xff0c;却显示以下提示&#xff0c;望高手解答。sudo: /etc/sudoers is world writablesudo: no valid sudoers sources found, quittingsudo: unable to initialize policy plugin 解决…

BGR转RGB

原图&#xff1a; 源代码&#xff1a; #codingutf-8#OpenCV读进来的图像,通道顺序为BGR&#xff0c; 而matplotlib的顺序为RGB&#xff0c;因此需要转换 import cv2 import numpy as np from matplotlib import pyplot as pltimg cv2.imread(./test1.jpg) B, G, R cv2.split…

C++ set的一些用法

set也是STL中比较常见的容器。set集合容器实现了红黑树的平衡二叉检索树的数据结构&#xff0c;它会自动调整二叉树的排列&#xff0c;把元素放到适当的位置。set容器所包含的元素的值是唯一的&#xff0c;集合中的元素按一定的顺序排列。 我们构造set集合的目的是为了快速的检…

ide在控制台输入编译命令_快速编译调试 Redis

一&#xff1a;开篇Redis 它是个宝&#xff0c;男女老少都说好。秒杀限流分布式&#xff0c;什么需求都能搞。Redis 主要的用途是分布式缓存&#xff0c;其实不用我多介绍&#xff0c;相信大家都用过Redis。之前也看过不少Redis的书&#xff0c;其中就包括《Redis设计与实现》。…

Java增强枚举的用例

Brian Goetz在消息“ 增强枚举-用例 ”中写道&#xff1a;“我们希望就现在实现的功能[ 增强枚举 ]获得用户反馈。” 他陈述了他的信息的第一个目的&#xff1a;“开始工作&#xff0c;这是一些通用枚举可能有用的典型用例。” 所提供的两个示例中的第一个示例是重构com.sun.to…

图片上传获取名字

Override public ResultResponse<String> uploadImg(MultipartFile file) { String imgUrl null; try { //MultipartFile类中两个方法区别&#xff1a;//getName : 获取表单中文件组件的名字//getOriginalFilename : 获取上传文件的原名 String name file.getOriginalF…

tf.nn.softmax

通过Softmax回归&#xff0c;将logistic的预测二分类的概率的问题推广到了n分类的概率的问题。通过公式 可以看出当月分类的个数变为2时&#xff0c;Softmax回归又退化为logistic回归问题。 下面的几行代码说明一下用法 # -*- coding: utf-8 -*- import tensorflow as tfA […

python easygui_python简单图形界面GUI入门——easygui

首先是easygui包下载&#xff0c;两种方式&#xff1a;1)在命令行提示符环境下&#xff0c;用pip install easygui直接安装&#xff1a;2)从http://easygui.sourceforge.net下载。将下载得到的easygui.py文件&#xff0c;复制到Python安装路 径下的Lib文件夹中。等待安装完成即…

使用 Python ElementTree 生成 xml

Python 处理 xml 文档的方法有很多&#xff0c;除了经典的 sax 和 dom 之外&#xff0c;还有一个 ElementTree。 首先 import 之&#xff1a; 1from xml.etree import ElementTree as etree然后开始构建 xml 树&#xff1a; 1234567891011121314from xml.etree.ElementTree imp…

卷积核输出维度计算

1&#xff09;卷积层&#xff1a; 参数&#xff1a;W&#xff1a;宽&#xff1b; H&#xff1a;高&#xff1b; D&#xff1a;深度&#xff1b; K&#xff1a;卷积核的个数&#xff1b; F&#xff1a;卷积核的大小&#xff1b; S&#xff1a;步长&#xff1b; P&#xff1a;…

接受与返回json数据

转载于:https://www.cnblogs.com/classmethond/p/10801606.html

归一化方法列举

归一化方法&#xff1a;除以序列最大值的&#xff0c;叫峰归一化&#xff1b;除以序列之和的&#xff0c;叫面积归一化&#xff1b;除以序列的模&#xff0c;叫数值归一化&#xff0c;得到序列的方差为0&#xff0c;均值为1&#xff1b;(1) 线性函数转换&#xff0c;表达式如下…

定时器和promise_手写Promise核心原理,再也不怕面试官问我Promise原理

整体流程的介绍 整体流程的介绍1. 定义整体结构2. 实现Promise构造函数3. 实现then方法3.实现catch方法4. 实现Promise.resolve5.实现Promise.reject6.实现Promise.all7.实现Promise.race文章会配合例子来讲解为什么要这么实现&#xff0c;尽我所能讲得粗俗易懂。有什么不理解或…

在Java 9中使用sun.misc.Unsafe

Java 9 EA版本已经发布&#xff0c;现在我们可以看到如何使用sun.misc.Unsafe。 我领导了公开运动&#xff0c;以保留对Java 9的访问&#xff0c;该访问最终成功&#xff0c;从而导致对JEP 260的修订。 那么&#xff0c;事情如何结束&#xff1f; 设定 首先&#xff0c;您需要…