springBoot 多数据源事务的管理以及回滚
来源:互联网 发布:邮电大学网络教育 编辑:程序博客网 时间:2024/06/06 15:47
最近开发的项目中使用到了多数据源,也使用到了两个不同事务的回滚事件,保证数据的一致性。部分代码共大家参考:MYSQL作为事例。
配置文件
spring.datasource.prod.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.prod.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.prod.username=root
spring.datasource.prod.password=root
spring.datasource.dev.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.dev.url=jdbc:mysql://127.0.0.1:3306/test1
spring.datasource.dev.username=root
spring.datasource.dev.password=root
配置数据源以及事务的管理
package com.lanwon.config;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import com.alibaba.druid.pool.DruidDataSource;
/**
* @author dzb
* @date 2017年8月23日
* 数据源dev
*/
@Configuration#不同的数据源扫描dao时要分层次,否则只能被绑定一次。
@MapperScan(basePackages="com.lanwon.mapper.dev",sqlSessionFactoryRef="devSqlSessionFactory")
public class devDataSourceConfig {
@Value("${spring.datasource.dev.driver-class-name}")
private String dbDriver;
@Value("${spring.datasource.dev.url}")
private String dbUrl;
@Value("${spring.datasource.dev.username}")
private String userName;
@Value("${spring.datasource.dev.password}")
private String password;
@Resource
private GlobalDbConfig globalDbConfig;
private static final String MAPPER_PATH = "classpath*:/mapper/dev/*.xml";
private static final String ENTITY_PACKAGE = "com.lanwon.entity.dev";
@Bean(name = "devDataSource")
@Primary
public DataSource devDataSource() throws SQLException {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(dbDriver);
dataSource.setUrl(dbUrl);
dataSource.setUsername(userName);
dataSource.setPassword(password);
dataSource.setFilters(globalDbConfig.getDbFilters());
dataSource.setMaxActive(globalDbConfig.getDbMaxActive());
dataSource.setMaxWait(globalDbConfig.getDbMaxWait());
dataSource.setMinIdle(globalDbConfig.getDbMinIdle());
dataSource.setTimeBetweenEvictionRunsMillis(globalDbConfig
.getDbTimeBetweenEvictionRunsMillis());
dataSource.setMinEvictableIdleTimeMillis(globalDbConfig
.getDbMinEvictableIdleTimeMillis());
dataSource.setTestWhileIdle(globalDbConfig.isDbtestWhileIdle());
dataSource.setValidationQuery(globalDbConfig.getDbValidationQuery());
dataSource.setTestOnBorrow(globalDbConfig.isDbTestOnBorrow());
dataSource.setTestOnReturn(globalDbConfig.isDbTestOnReturn());
dataSource.setPoolPreparedStatements(globalDbConfig
.isDbPoolPreparedStatements());
dataSource.setMaxOpenPreparedStatements(globalDbConfig
.getDbMaxOpenPreparedStatements());
dataSource.init();
return dataSource;
}
@Bean(name = "devTransactionManager")
@Primary
public DataSourceTransactionManager devTransactionManager()
throws SQLException {
return new DataSourceTransactionManager(devDataSource());
}
@Bean(name = "devSqlSessionFactory")
@Primary //默认
public SqlSessionFactory devSqlSessionFactory(
@Qualifier("devDataSource") DataSource ddataSource)
throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(ddataSource);
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sessionFactory.setMapperLocations(resolver.getResources(MAPPER_PATH));
sessionFactory.setTypeAliasesPackage(ENTITY_PACKAGE);
return sessionFactory.getObject();
}
}
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import com.alibaba.druid.pool.DruidDataSource;
/**
* @author dzb
* @date 2017年8月23日
* 数据源prod
*/
@Configuration
@MapperScan(basePackages="com.lanwon.mapper.prod",sqlSessionFactoryRef="prodSqlSessionFactory")
public class prodDataSourcesConfig {
@Value("${spring.datasource.prod.driver-class-name}")
private String dbDriver;
@Value("${spring.datasource.prod.url}")
private String dbUrl;
@Value("${spring.datasource.prod.username}")
private String userName;
@Value("${spring.datasource.prod.password}")
private String password;
@Resource
private GlobalDbConfig globalDbConfig;
private static final String MAPPER_PATH = "classpath*:/mapper/prod/*.xml";
private static final String ENTITY_PACKAGE = "com.lanwon.entity.prod";
@Bean(name = "prodDataSource")
public DataSource prodDataSource() throws SQLException {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(dbDriver);
dataSource.setUrl(dbUrl);
dataSource.setUsername(userName);
dataSource.setPassword(password);
dataSource.setFilters(globalDbConfig.getDbFilters());
dataSource.setMaxActive(globalDbConfig.getDbMaxActive());
dataSource.setMaxWait(globalDbConfig.getDbMaxWait());
dataSource.setMinIdle(globalDbConfig.getDbMinIdle());
dataSource.setTimeBetweenEvictionRunsMillis(globalDbConfig
.getDbTimeBetweenEvictionRunsMillis());
dataSource.setMinEvictableIdleTimeMillis(globalDbConfig
.getDbMinEvictableIdleTimeMillis());
dataSource.setTestWhileIdle(globalDbConfig.isDbtestWhileIdle());
dataSource.setValidationQuery(globalDbConfig.getDbValidationQuery());
dataSource.setTestOnBorrow(globalDbConfig.isDbTestOnBorrow());
dataSource.setTestOnReturn(globalDbConfig.isDbTestOnReturn());
dataSource.setPoolPreparedStatements(globalDbConfig
.isDbPoolPreparedStatements());
dataSource.setMaxOpenPreparedStatements(globalDbConfig
.getDbMaxOpenPreparedStatements());
dataSource.init();
return dataSource;
}
@Bean(name = "prodTransactionManager")
public DataSourceTransactionManager prodTransactionManager()
throws SQLException {
return new DataSourceTransactionManager(prodDataSource());
}
@Bean(name = "prodSqlSessionFactory")
public SqlSessionFactory prodSqlSessionFactory(
@Qualifier("prodDataSource") DataSource pdataSource)
throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(pdataSource);
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sessionFactory.setMapperLocations(resolver.getResources(MAPPER_PATH));
sessionFactory.setTypeAliasesPackage(ENTITY_PACKAGE);
return sessionFactory.getObject();
}
}
使用事务管理器
使用时只需在需要事务的方法添加注解@Transactional
,并指定其value值即可。同样的,value值与相应的事务管理方法名相匹配即可。
/**
* @author dzb
* @since 2016/7/5 - 22:21
*/
@Service
public class UserDetailServiceImpl implements UserDetailService {
@Autowired
private UserDetailMapper userDetailMapper;
public List<UserDetail> selectUserDetail() {
return userDetailMapper.selectAll();
}
@Transactional(value="devTransactionManager")
@Override
public int update(UserDetail userDetail){
int b=userDetailMapper.update(userDetail);
return b;
}
}
@Service
public class UserInfoServiceImpl implements UserInfoService {
@Autowired
private UserInfoMapper userInfoMapper;
@Autowired
private UserDetailServiceImpl detailServiceImpl ;
public List<UserInfo> selectUserInfo() {
return userInfoMapper.selectAll();
}
//@Transactional(value="prodTransactionManager")
@Override
public int update(UserInfo userInfo) {
int a =userInfoMapper.update(userInfo);
return a;
}
@Transactional(value="prodTransactionManager")
@Override
public int update(String name1,String name2) {
int c=0;
UserInfo info = new UserInfo();
info.setId("1");
info.setUsername(name1);
int b=userInfoMapper.update(info);
if(b>0){
UserDetail detail = new UserDetail();
detail.setId(1L);
detail.setName(name2);
c=detailServiceImpl.update(detail);
}
return c;
}
}
事务传播行为种类
Spring在TransactionDefinition接口中规定了7种类型的事务传播行为,
它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播:
表1事务传播行为类型
事务传播行为类型
说明
PROPAGATION_REQUIRED
如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY
使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW
新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
注:这篇文章是本人自己所遇到写的,如果有不太对的地方,请多多指教。
项目源码github:https://github.com/sdmxdzb/transcations
- springBoot 多数据源事务的管理以及回滚
- Atomikos+Spring+Hibernate支持多数据源+事务回滚
- SpringBoot多数据源及事务配置
- SpringBoot多数据源配置事务
- springboot多数据源配置事务
- SpringBoot多数据源 + Atomikos事务
- eclipse+maven+springboot+多数据源事物回滚+jsp+freemarker
- springboot多数据源指定不同事务管理器
- 演示多数据源分布式事务的最小化Springboot Web应用
- 数据库的事务,事务的特性以及回滚
- springboot 多数据源
- springboot多数据源
- springboot的多数据源配置
- SpringBoot的多数据源配置
- springBoot+mybatis多数据源的配置
- SpringBoot JPA 多数据源的使用
- springBoot 动态数据源以及Mybatis多数据源
- SpringBoot多数据源的配置(SpringBoot+MyBatis)
- 将JBoss启动做成Windows的系统服务
- linux 实现shell睡眠脚本
- 杂题
- 【线段树区间更新 && 染色】ZOJ
- c++用WinForm做界面的实现
- springBoot 多数据源事务的管理以及回滚
- Android studio 命令行运行gradle命令
- (HDU
- Listview多条目的代码
- js原生数组工具方法总结
- Python学习笔记——20170823
- code force-27C---Unordered Subsequence (模拟+暴力)
- ES6新特性
- WHQL认证中搭建了服务器和客户端,计算机池中Selection中无任何选项的解决方案