- 浏览: 3208 次
- 性别:
- 来自: 成都
文章分类
最新评论
一.单一数据源的事务管理
事务的管理有几种方式, 使用注解, 声明式配置等等.
首先,看一下单一数据源的事务配置:
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- 扫描注解Bean -->
<context:component-scan base-package="com.tx">
</context:component-scan>
<tx:annotation-driven proxy-target-class="true"
transaction-manager="txManager" />
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="jdbctemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="txManager" />
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="clear*">PROPAGATION_REQUIRED</prop>
<prop key="restore*">PROPAGATION_REQUIRED</prop>
<prop key="replace*">PROPAGATION_REQUIRED</prop>
<prop key="process*">PROPAGATION_REQUIRED</prop>
<prop key="execute*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!-- 设置代理类 -->
<bean id="bdf.transaction.beanNameAutoProxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="proxyTargetClass" value="true"></property>
<property name="beanNames" value="*PR,*BO,*Service,*Dao" />
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
<!-- 设置事务管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!--
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
基本属性 url、user、password
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
配置初始化大小、最小、最大
<property name="initialSize" value="1" />
<property name="minIdle" value="1" />
<property name="maxActive" value="20" />
配置获取连接等待超时的时间
<property name="maxWait" value="60000" />
配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
<property name="timeBetweenEvictionRunsMillis" value="60000" />
配置一个连接在池中最小生存的时间,单位是毫秒
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="validationQuery" value="SELECT * from user" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
打开PSCache,并且指定每个连接上PSCache的大小
<property name="poolPreparedStatements" value="true" />
<property name="maxPoolPreparedStatementPerConnectionSize"
value="20" />
配置监控统计拦截的filters
<property name="filters" value="stat" />
</bean> -->
<!-- 配置数据源,c3p0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
</beans>
其中transactionInterceptor中配置的拦截方法就是需要事务管理的, 满足命名条件的方法都会被事务管理所拦截.
测试:
/* Dao代码 */
public class JdbcTestDao {
@Resource(name="jdbctemplate")
JdbcTemplate jdbcTemplate;
/**
* 在配置文件中使用了声明式的事务管理,<prop key="execute*">PROPAGATION_REQUIRED</prop>
* 所以这个事务是会被拦截的事务
*/
public void execute(){
jdbcTemplate.update("UPDATE user set username = 'fff1' where id=4");
jdbcTemplate.update("UPDATE user1 set username = 'eee1' where id=4");
int i = 1/0;
}
/**
* 这个虽然不是在配置文件中需要被拦截的事务,但是有注解声明
* 所以这个事务是会被拦截的事务
*/
@Transactional
public void notExtcuteWithTx(){
jdbcTemplate.update("UPDATE user set username = 'ggg' where id=4");
jdbcTemplate.update("UPDATE user1 set username = 'hhh' where id=4");
int i = 1/0;
}
/**
* 不会被拦截的事务
*/
public void notExtcute(){
jdbcTemplate.update("UPDATE user set username = 'iii' where id=4");
jdbcTemplate.update("UPDATE user1 set username = 'jjjj' where id=4");
int i = 1/0;
}
}
/* jUnit代码 */
public class JdbcTestDaoTest {
ApplicationContext context;
@Before
public void before() {
context = new ClassPathXmlApplicationContext("spring-jdbc.xml");
}
@Test
public void execute() {
JdbcTestDao dao = context.getBean(JdbcTestDao.class);
dao.execute();
}
@Test
public void notExtcuteWithTx() {
JdbcTestDao dao = context.getBean(JdbcTestDao.class);
dao.notExtcuteWithTx();
}
@Test
public void notExtcute() {
JdbcTestDao dao = context.getBean(JdbcTestDao.class);
dao.notExtcute();
}
}
分别单元测试三个方法, 可以得到正确的结果, 当抛出异常的时候, 事务都会回滚.
二.多数据源的事务管理
在spring中, 提供了很多事务管理的接口, DataSourceTransactionManager, JpaTransactionManager, JtaTransactionManager等等. 其中JtaTransactionManager是专门用来管理多数据源, 提供了对分布式事务的支持.
<!-- JTA分布式事务配置 -->
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- 扫描注解Bean -->
<context:component-scan base-package="com.tx">
</context:component-scan>
<tx:annotation-driven proxy-target-class="true"
transaction-manager="transactionManager" />
<bean id="jdbctemplate1" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource1" />
</bean>
<bean id="jdbctemplate2" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource2" />
</bean>
<bean id="dataSource1" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="mysql1" />
<property name="xaDataSourceClassName"
value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
<property name="xaProperties">
<props>
<prop key="url">jdbc:mysql://localhost:3306/chatroom?useUnicode=true&characterEncoding=utf8
</prop>
<prop key="user">root</prop>
<prop key="password">123456</prop>
<!-- <prop key="initialSize">1</prop> <prop key="minIdle">1</prop> <prop
key="maxActive">20</prop> -->
</props>
</property>
<property name="minPoolSize" value="10" />
<property name="maxPoolSize" value="100" />
<property name="borrowConnectionTimeout" value="30" />
<property name="testQuery" value="select 1" />
<property name="maintenanceInterval" value="60" />
</bean>
<bean id="dataSource2" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="mysql2" />
<property name="xaDataSourceClassName"
value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
<property name="xaProperties">
<props>
<prop key="url">jdbc:mysql://localhost:3306/cms?useUnicode=true&characterEncoding=utf8
</prop>
<prop key="user">root</prop>
<prop key="password">123456</prop>
<!-- <prop key="initialSize">1</prop> <prop key="minIdle">1</prop> <prop
key="maxActive">20</prop> -->
</props>
</property>
<property name="minPoolSize" value="10" />
<property name="maxPoolSize" value="100" />
<property name="borrowConnectionTimeout" value="30" />
<property name="testQuery" value="select 1" />
<property name="maintenanceInterval" value="60" />
</bean>
<!-- 设置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<property name="forceShutdown" value="true" />
</bean>
</property>
<property name="userTransaction">
<bean class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
</property>
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="clear*">PROPAGATION_REQUIRED</prop>
<prop key="restore*">PROPAGATION_REQUIRED</prop>
<prop key="replace*">PROPAGATION_REQUIRED</prop>
<prop key="process*">PROPAGATION_REQUIRED</prop>
<prop key="execute*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!-- 设置代理类 -->
<bean id="transactionBeanNameAutoProxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="proxyTargetClass" value="true"></property>
<property name="beanNames" value="*PR,*BO,*Service,*Dao" />
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
</beans>
这里,使用的都是mysql, 只是数据库不同, 也可以使用多种数据库,可替换为oracle等.
测试:
/* Dao代码 */
@Component
public class JtaTestDao implements ApplicationContextAware ,InitializingBean{
private ApplicationContext context;
public void execute() {
JdbcTemplate chatroom = context.getBean("jdbctemplate1",
JdbcTemplate.class);
JdbcTemplate cms = context.getBean("jdbctemplate2",
JdbcTemplate.class);
chatroom.update("UPDATE user set username = 'lzxfgw' where id=4");
cms.update("INSERT INTO c_user (id, login_name, password) values (100, 'fgw', '123')");
}
//@PostConstruct
//实现ApplicationContextAware接口, 可以在初始化的时候注入applicationContext
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.context = applicationContext;
}
@Override
public void afterPropertiesSet() throws Exception {
}
}
/* jUnit代码 */
public class JtaTestDaoTest {
ApplicationContext context;
@Test
public void test() {
JtaTestDao t = context.getBean(JtaTestDao.class);
t.execute();
}
@Before
public void before() {
context = new ClassPathXmlApplicationContext("spring-jta.xml");
}
}
运行jUnit第一次是没有问题的, 修改一下dao代码中的username再次运行,会抛出主键重复的异常, 可以看到数据库中的第一条update语句的username也没有改变, 说明事务在抛出异常之后正常回滚了.
事务的管理有几种方式, 使用注解, 声明式配置等等.
首先,看一下单一数据源的事务配置:
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- 扫描注解Bean -->
<context:component-scan base-package="com.tx">
</context:component-scan>
<tx:annotation-driven proxy-target-class="true"
transaction-manager="txManager" />
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="jdbctemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="txManager" />
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="clear*">PROPAGATION_REQUIRED</prop>
<prop key="restore*">PROPAGATION_REQUIRED</prop>
<prop key="replace*">PROPAGATION_REQUIRED</prop>
<prop key="process*">PROPAGATION_REQUIRED</prop>
<prop key="execute*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!-- 设置代理类 -->
<bean id="bdf.transaction.beanNameAutoProxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="proxyTargetClass" value="true"></property>
<property name="beanNames" value="*PR,*BO,*Service,*Dao" />
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
<!-- 设置事务管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!--
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
基本属性 url、user、password
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
配置初始化大小、最小、最大
<property name="initialSize" value="1" />
<property name="minIdle" value="1" />
<property name="maxActive" value="20" />
配置获取连接等待超时的时间
<property name="maxWait" value="60000" />
配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
<property name="timeBetweenEvictionRunsMillis" value="60000" />
配置一个连接在池中最小生存的时间,单位是毫秒
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="validationQuery" value="SELECT * from user" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
打开PSCache,并且指定每个连接上PSCache的大小
<property name="poolPreparedStatements" value="true" />
<property name="maxPoolPreparedStatementPerConnectionSize"
value="20" />
配置监控统计拦截的filters
<property name="filters" value="stat" />
</bean> -->
<!-- 配置数据源,c3p0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
</beans>
其中transactionInterceptor中配置的拦截方法就是需要事务管理的, 满足命名条件的方法都会被事务管理所拦截.
测试:
/* Dao代码 */
public class JdbcTestDao {
@Resource(name="jdbctemplate")
JdbcTemplate jdbcTemplate;
/**
* 在配置文件中使用了声明式的事务管理,<prop key="execute*">PROPAGATION_REQUIRED</prop>
* 所以这个事务是会被拦截的事务
*/
public void execute(){
jdbcTemplate.update("UPDATE user set username = 'fff1' where id=4");
jdbcTemplate.update("UPDATE user1 set username = 'eee1' where id=4");
int i = 1/0;
}
/**
* 这个虽然不是在配置文件中需要被拦截的事务,但是有注解声明
* 所以这个事务是会被拦截的事务
*/
@Transactional
public void notExtcuteWithTx(){
jdbcTemplate.update("UPDATE user set username = 'ggg' where id=4");
jdbcTemplate.update("UPDATE user1 set username = 'hhh' where id=4");
int i = 1/0;
}
/**
* 不会被拦截的事务
*/
public void notExtcute(){
jdbcTemplate.update("UPDATE user set username = 'iii' where id=4");
jdbcTemplate.update("UPDATE user1 set username = 'jjjj' where id=4");
int i = 1/0;
}
}
/* jUnit代码 */
public class JdbcTestDaoTest {
ApplicationContext context;
@Before
public void before() {
context = new ClassPathXmlApplicationContext("spring-jdbc.xml");
}
@Test
public void execute() {
JdbcTestDao dao = context.getBean(JdbcTestDao.class);
dao.execute();
}
@Test
public void notExtcuteWithTx() {
JdbcTestDao dao = context.getBean(JdbcTestDao.class);
dao.notExtcuteWithTx();
}
@Test
public void notExtcute() {
JdbcTestDao dao = context.getBean(JdbcTestDao.class);
dao.notExtcute();
}
}
分别单元测试三个方法, 可以得到正确的结果, 当抛出异常的时候, 事务都会回滚.
二.多数据源的事务管理
在spring中, 提供了很多事务管理的接口, DataSourceTransactionManager, JpaTransactionManager, JtaTransactionManager等等. 其中JtaTransactionManager是专门用来管理多数据源, 提供了对分布式事务的支持.
<!-- JTA分布式事务配置 -->
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- 扫描注解Bean -->
<context:component-scan base-package="com.tx">
</context:component-scan>
<tx:annotation-driven proxy-target-class="true"
transaction-manager="transactionManager" />
<bean id="jdbctemplate1" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource1" />
</bean>
<bean id="jdbctemplate2" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource2" />
</bean>
<bean id="dataSource1" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="mysql1" />
<property name="xaDataSourceClassName"
value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
<property name="xaProperties">
<props>
<prop key="url">jdbc:mysql://localhost:3306/chatroom?useUnicode=true&characterEncoding=utf8
</prop>
<prop key="user">root</prop>
<prop key="password">123456</prop>
<!-- <prop key="initialSize">1</prop> <prop key="minIdle">1</prop> <prop
key="maxActive">20</prop> -->
</props>
</property>
<property name="minPoolSize" value="10" />
<property name="maxPoolSize" value="100" />
<property name="borrowConnectionTimeout" value="30" />
<property name="testQuery" value="select 1" />
<property name="maintenanceInterval" value="60" />
</bean>
<bean id="dataSource2" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="mysql2" />
<property name="xaDataSourceClassName"
value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
<property name="xaProperties">
<props>
<prop key="url">jdbc:mysql://localhost:3306/cms?useUnicode=true&characterEncoding=utf8
</prop>
<prop key="user">root</prop>
<prop key="password">123456</prop>
<!-- <prop key="initialSize">1</prop> <prop key="minIdle">1</prop> <prop
key="maxActive">20</prop> -->
</props>
</property>
<property name="minPoolSize" value="10" />
<property name="maxPoolSize" value="100" />
<property name="borrowConnectionTimeout" value="30" />
<property name="testQuery" value="select 1" />
<property name="maintenanceInterval" value="60" />
</bean>
<!-- 设置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<property name="forceShutdown" value="true" />
</bean>
</property>
<property name="userTransaction">
<bean class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
</property>
</bean>
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager" />
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="clear*">PROPAGATION_REQUIRED</prop>
<prop key="restore*">PROPAGATION_REQUIRED</prop>
<prop key="replace*">PROPAGATION_REQUIRED</prop>
<prop key="process*">PROPAGATION_REQUIRED</prop>
<prop key="execute*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!-- 设置代理类 -->
<bean id="transactionBeanNameAutoProxyCreator"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="proxyTargetClass" value="true"></property>
<property name="beanNames" value="*PR,*BO,*Service,*Dao" />
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
</beans>
这里,使用的都是mysql, 只是数据库不同, 也可以使用多种数据库,可替换为oracle等.
测试:
/* Dao代码 */
@Component
public class JtaTestDao implements ApplicationContextAware ,InitializingBean{
private ApplicationContext context;
public void execute() {
JdbcTemplate chatroom = context.getBean("jdbctemplate1",
JdbcTemplate.class);
JdbcTemplate cms = context.getBean("jdbctemplate2",
JdbcTemplate.class);
chatroom.update("UPDATE user set username = 'lzxfgw' where id=4");
cms.update("INSERT INTO c_user (id, login_name, password) values (100, 'fgw', '123')");
}
//@PostConstruct
//实现ApplicationContextAware接口, 可以在初始化的时候注入applicationContext
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.context = applicationContext;
}
@Override
public void afterPropertiesSet() throws Exception {
}
}
/* jUnit代码 */
public class JtaTestDaoTest {
ApplicationContext context;
@Test
public void test() {
JtaTestDao t = context.getBean(JtaTestDao.class);
t.execute();
}
@Before
public void before() {
context = new ClassPathXmlApplicationContext("spring-jta.xml");
}
}
运行jUnit第一次是没有问题的, 修改一下dao代码中的username再次运行,会抛出主键重复的异常, 可以看到数据库中的第一条update语句的username也没有改变, 说明事务在抛出异常之后正常回滚了.
相关推荐
1. 基于Aspectj实现动态数据源...6. 实现事务内切换数据源(支持原生Spring声明式事务哟,仅此一家),并支持多数据源事务回滚(有了它除了跨服务的事务你需要考虑分布式事务,其他都不需要,极大的减少了系统的复杂程度)
Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis
由于网上的多数据源事务的帖子大多是2010年以前的,现在spring都已经到4.X了,有些类已经弃用了。 原先很多都是用jotm实现的,但是由于spring的升级,totm的本地化实例那个类已经找不到了,所以我使用了atomikos。 ...
spring+jotm 多数据源事务管理(三)JNDI+Tomcat 首先需要将jotm相关jar包加入到tomcat中,如下: o jotm.jar o jotm_jrmp_stubs.jar o ow_carol.jar o jta.jar o jta-spec1_0_1.jar o jts1_0.jar o objectweb-...
用springboot 集成mybatis多数据源,用aop实现的动态切换,支持事务,不会使aop动态切换失效。注意:此代码不涉及分布式事务,如果需要分布式事务 需要采取其他方案。
spring+jotm 多数据源事务管理(二)hibernate 使用hibernate关联jotm也很方便,先看一个没有使用jotm的例子:
实现系统对多数据源的操作。 实现系统对多数据源的分布式事务管理,包括事务的提交和回滚。
spring+druid+AtomikosDataSource实现多数据源切换及分布式事务控制
实现系统对多数据源的操作。 实现系统对多数据源的分布式事务管理,包括事务的提交和回滚。
springboot mybatis多数据源加事务嵌套 事务之间的调用 回滚 亲测可用 定义2个库分别建立 CREATE TABLE `user` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户编号', `user_name` varchar(25) ...
spring+hibernate+atomikos实现多数据源分布式事务管理
spring jdbcTemplate 多数据源切换数据库操作,junit测试。
Spring boot+Atomikos+JTA+Hibernate+MySQL实现分布式事务+多数据源,分别向两个不同的数据里面插入数据同时失败和成功,调用接口方式原理一样。
spring事务操作试验 博客地址:https://blog.csdn.net/u010476739/article/details/99130972
spring的annotation-driven配置事务管理器详解 (多数据源配置
本用例基于 Spring Boot + Druid + Mybatis 配置多数据源,并采用 JTA 实现分布式事务。
springboot+mybatis双数据源配置及事务处理
Spring3.0配置多个事务管理器(即操作多个数据源)的方法 大多数项目只需要一个事务管理器。然而,有些项目为了提高效率、或者有多个完全不同又不相干的数据源,最好用多个事务管理器。机智的Spring的Transactional...
spring事务以及分布式事务实现.zip one-data-source 单数据源事务 two-data-source 多数据源事务 ...使用atomikos管理多数据源事务 多数据源事务结合Druid数据库连接池 代码包括声明式事务和编程式事务
Spring Data JPA系列4——Spring声明式事务处理与多数据源支持.doc