Atomikos实现多数据源的事物管理
之前试过使用Spring动态切换数据库,通过继承AbstractRoutingDataSource重写determineCurrentLookupKey()方法,来决定使用那个数据库。在开启事务之前,通过改变lookupKey来达到切换数据源目的。但是这种方法多个数据库之前没办法做事务管理,或许对于主从(读写)数据库会好用一些,而对于需要一个操作中更新多个数据库的情况,使用Atomikos或许会更好一些。
本文采用spring4+hibernate4+Atomikos进行事务管理。
依赖dependency
Atomikos要使用的库使用maven导入,spring和hibernate的依赖就不一一列出,需要额外添加的dependency如下:
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>atomikos-util</artifactId>
<version>3.9.3</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jdbc</artifactId>
<version>3.9.3</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jta</artifactId>
<version>3.9.3</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions</artifactId>
<version>3.9.3</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-api</artifactId>
<version>3.9.3</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
使用的数据库驱动依赖如下:
<!-- 加入mysql驱动依赖包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
<!-- sql server数据库驱动 -->
<dependency>
<groupId>net.sourceforge.jtds</groupId>
<artifactId>jtds</artifactId>
<version>1.3.1</version>
</dependency>
<!-- 加入druid数据源依赖包 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.26</version>
</dependency>
有点需要注意的是,druid的版本应该跟上mysql的版本,不然可能找不到MySQL的XADataSource。
配置configuration
配置数据源xml代码:
<bean id="mysql" class="com.alibaba.druid.pool.xa.DruidXADataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc_url}" />
<property name="username" value="${jdbc_username}" />
<property name="password" value="${jdbc_password}" /> <!-- 初始化连接大小 -->
<property name="initialSize" value="0" />
<!-- 连接池最大使用连接数量 -->
<property name="maxActive" value="20" />
<!-- 连接池最小空闲 -->
<property name="minIdle" value="0" />
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="60000" />
<!-- <property name="poolPreparedStatements" value="true" />
<property name="maxPoolPreparedStatementPerConnectionSize" value="33" /> -->
<property name="validationQuery" value="SELECT 1" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<property name="testWhileIdle" value="true" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="25200000" />
<!-- 打开removeAbandoned功能 -->
<property name="removeAbandoned" value="true" />
<!-- 1800秒,也就是30分钟 -->
<property name="removeAbandonedTimeout" value="1800" />
<!-- 关闭abanded连接时输出错误日志 -->
<property name="logAbandoned" value="true" /> <!-- 监控数据库 -->
<!-- <property name="filters" value="mergeStat" /> -->
<!-- <property name="filters" value="stat" /> -->
<!--<property name="filters" value="config" />
<property name="connectionProperties" value="config.decrypt=true" />-->
</bean> <bean id="mysqlDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<!-- Set unique name for this DataSource -->
<property name="uniqueResourceName">
<value>mysql</value>
</property>
<!-- Set XADatasource class name-->
<property name="xaDataSource" ref="mysql"/>
<!-- 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>
配置SessionFactory的xml代码:
<bean id="noticesSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="mysqlDataSource" />
<property name="jtaTransactionManager" ref="springTransactionManager"></property>
<property name="packagesToScan">
<list>
<value>com.test.model</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<!-- 慎重(推荐禁止) 固定为update -->
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.autoReconnect">true</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.use_sql_comments">${hibernate.use_sql_comments}</prop>
<prop key="hibernate.jdbc.batch_size">${hibernate.batch_size}</prop>
</props>
</property>
</bean>
如果要使用getCurrentSession()的话,要注意加上:
<property name="jtaTransactionManager" ref="springTransactionManager"></property>
添加多个数据库的话,只需要把上面的xml再写一遍。
下面配置atomikos的事务管理器xml代码:
<!-- 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的事务管理器xml代码:
<!-- 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> <!-- 注解方式配置事物-->
<tx:annotation-driven transaction-manager="springTransactionManager" />
添加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=false # 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
好了,Atomikos算是配置完成,我们可以写代码测试一下。测试的代码这里就不写出了。
性能优化
总结
这么长的配置文件要小心点写,我的粗心结果就是datasource乱套了,导致花了不少时间排错。当然还有各种乱七八糟的糟心问题,这些问题会在后面的文章中列出来,大家可以注意避免。最后用上Atomikos的分布式事务,没有了各种的脏数据,舒心了不少。
Atomikos实现多数据源的事物管理的更多相关文章
- springBoot的事物管理
springBoot的事物管理 1:springBoot 整合单数据源事物: Spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务 ...
- SpringBoot事物管理器
一.springboot整合事物管理 springboot默认集成事物,只主要在方法上加上@Transactional即可 二.SpringBoot分布式事物管理 使用springboot+jta+a ...
- [原创]java WEB学习笔记109:Spring学习---spring中事物管理
博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好 ...
- Spring中的事物管理,基于spring的bean的配置
很多东西与上边的相同,这儿只简介: 导包... 数据库中建立三个表... 建立存放连接数据库的file文件:jdbc.properties: ----------------------------- ...
- Spring中的事物管理,用 @Transactional 注解声明式地管理事务
事物: 事务管理是企业级应用程序开发中必不可少的技术, 用来确保数据的 完整性和 一致性. 事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用 事务的四 ...
- Spring学习之声明式事物管理
public List<Student> selectStudent() { Student s = new Student(); s.setName("zhengbin&quo ...
- springboot整合多数据源及事物
有两种方式:一种是分包的方式.一种是加注解的方式(@DataSource(ref="")). 分包方式:项目结构图如下: 分为com.itmayiedu.test01.com.it ...
- Spring中的事物管理----HelloWorld
在学习Spring的事物管理之前明白先明白几个概念1什么是事物:事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用例子说明:例如银行转账,A账户转账(转2 ...
- SSH学习——声明式事物管理(Spring)
1.什么是事物? 事务是一组操作的执行单元,相对于数据库操作来讲,事务管理的是一组SQL指令,比如增加,修改,删除等,事务的一致性,要求,这个事务内的操作必须全部执行成功,如果在此过程种出现了差错,比 ...
随机推荐
- spring+mybatis多数据源动态切换
spring mvc+mybatis+多数据源切换 选取oracle,mysql作为例子切换数据源.oracle为默认数据源,在测试的action中,进行mysql和oracle的动态切换. web. ...
- eclipse SE增加Web开发插件
最近接触了些java项目,之前安装了eclipse SE版本.没有Web开发插件,调试不了Web代码.点击“Window”--“Preference” 左边菜单栏是找不到“Server”项来配置服务器 ...
- 【原】低版本MyEclipse整合高版本Tomcat
[使用工具] 1.MyEclipse_6.0.1GA_E3.3.1_FullStackInstaller 2.Tomcat 7.0 [问题描述] 直接在MyEclipse中整合,因为这个版本的MyEc ...
- Sqlite 存储自定义对象
在iOS中如果想保存自定义对象,要让自定义对象实现NSCoding接口并实现方法-(id)initWithCoder:(NSCoder *)coder和-(void)encodeWithCoder:( ...
- 基于SVN的项目管理——集中与分散
我们在此处不讨论 GIT 比 SVN 好多少,也不讨论 Maven 和 Gradle 哪个好用,基于现有的开发环境,大多数公司还是采用 SVN + Maven 来进行项目管理——因为这已经满足了大多数 ...
- Java 加解密 AES DES TripleDes
package xxx.common.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.crypt ...
- Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds
错误:Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds 错误提示就是我们限定了部署的时间导致的错 ...
- linux几种快速清空文件内容的方法
linux几种快速清空文件内容的方法 几种快速清空文件内容的方法: $ : > filename #其中的 : 是一个占位符, 不产生任何输出. $ > filename $ echo & ...
- 2、实现不同子网之间的信息交流(互相可以PING通)
一.环境: 二个不同的虚拟子网 VMnet1: 192.168.155.0/24 VMnet8: 192.168.170.0/24 编辑 --> 虚拟网络编辑器 (查看自己的子网,相应修改就行) ...
- “会”和 "好”纯粹是两个概念
你会吗? 如果我现在问下大家你会OOP 吗?你会OOD吗? 你知道SOLID吗?你会在实际工作中运用这些原则吗? 你知道模式吗,你会在实际项目中适时引入合理的设计模式来解决项目中的代码坏味吗? 你知道 ...