应用场景:双数据源,就是某些项目会涉及到两个数据源或者两个以上的数据源,这个多数据源的项目一般是数据同步,也就是把数据从另一个系统中,保存到另一个系统,两边的 数据库又不一样,比如一个Mysql、一个Sql Server。但是不管是什么类型的数据库,我们都不管,直接连接就是。

为什么要使用分布式事务:顾名思义,事务就是回滚,比如如果一个在保存数据的时候,在A数据库已经 保存,但是在保存数据在B的过程抛出异常,那么是不是应该全部回滚,把已经 保存了的A、B数据库的数据全部回滚?答案是确定的。下面就解说:

pom.xml主要依赖:

       <dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>

  

properties配置文件:

         #数据源一
spring.datasource.primary.url=jdbc:mysql://localhost:3306/test
spring.datasource.primary.username=root
spring.datasource.primary.password=root
spring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.primary.xa-data-source-class-name=com.alibaba.druid.pool.xa.DruidXADataSource

#数据源二
spring.datasource.secondary.url=jdbc:mysql://localhost:3306/test1
spring.datasource.secondary.username=root
spring.datasource.secondary.password=root
spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.secondary.xa-data-source-class-name=com.alibaba.druid.pool.xa.DruidXADataSource

 

数据源的配置类:DataSourceConfig.class

import com.alibaba.druid.pool.xa.DruidXADataSource;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; @Configuration
public class DataSourceConfig {
//这里一定要加主数据源的注解
@Primary
@Bean(name = "primaryProperty")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DruidXADataSource primaryDataSource() {
return new DruidXADataSource();
}

//这里是第二个数据源
@Bean(name = "secondaryProperty")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DruidXADataSource secondaryDataSource() {
return new DruidXADataSource();
}
}

  

再分别配置他们的数据源:以便包扫描、事务交给jta-atomikos统一管理

主数据源配置类:

import com.alibaba.druid.pool.xa.DruidXADataSource;
import com.atomikos.jdbc.AtomikosDataSourceBean; import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import javax.sql.DataSource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import tk.mybatis.spring.annotation.MapperScan; @Configuration
@MapperScan(basePackages = {"com.example.dao.primary"}, sqlSessionTemplateRef = "primarySqlSessionTemplate")
public class PrimaryDBConfig { @Bean(name = "primaryDataSource")
public DataSource dataSourceCar(@Qualifier("primaryProperty") DruidXADataSource druidXADataSource) {
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(druidXADataSource);
xaDataSource.setUniqueResourceName("primaryDataSource");
return xaDataSource;
} @Bean(name = "primarySqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/primary/*Mapper.xml"));//扫描指定目录的xml
return bean.getObject();
} @Bean(name = "primarySqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(
@Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}

  

同理,第二个数据源的配置SecondaryDBConfig.java

@Configuration
@MapperScan(basePackages = {"com.example.dao.secondary"}, sqlSessionTemplateRef = "secondarySqlSessionTemplate")
public class SecondaryDBConfig { @Bean(name = "secondaryDataSource")
public DataSource dataSourceCar(@Qualifier("secondaryProperty") DruidXADataSource druidXADataSource) {
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(druidXADataSource);
xaDataSource.setUniqueResourceName("secondaryDataSource");
return xaDataSource;
} @Bean(name = "secondarySqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("secondaryDataSource") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/secondary/*Mapper.xml"));//扫描指定目录的xml
return bean.getObject();
} @Bean(name = "secondarySqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(
@Qualifier("secondarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}

  

最后我们还需要配置事务管理的配置类:TransactionManagerConfig.java,以便把数据源一,数据源二全部交给jta-atomikos管理,实现分布式事务管理:

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.jta.JtaTransactionManager; import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction; @Configuration
public class TransactionManagerConfig { @Bean(name = "userTransaction")
public UserTransaction userTransaction() throws Throwable {
UserTransactionImp userTransactionImp = new UserTransactionImp();
userTransactionImp.setTransactionTimeout(10000);
return userTransactionImp;
} @Bean(name = "atomikosTransactionManager")
public TransactionManager atomikosTransactionManager() throws Throwable {
UserTransactionManager userTransactionManager = new UserTransactionManager();
userTransactionManager.setForceShutdown(false);
return userTransactionManager;
} @Bean(name = "transactionManager")
@DependsOn({ "userTransaction", "atomikosTransactionManager" })
public PlatformTransactionManager transactionManager() throws Throwable {
return new JtaTransactionManager(userTransaction(),atomikosTransactionManager());
}
}

  最后我们在service类上加上注解:@Transactional(value = "transactionManager", rollbackFor = Exception.class)

当value = "transactionManager",则是分布式事务的管理。至此,全部完成。

gitHub完整项目下载地址:https://gitee.com/qhThomas/springboot-mybatis-duria.git

最新文章

  1. CoreCLR源码探索(一) Object是什么
  2. Android带边框表格的实现
  3. Centos7 关闭防火墙(Firewalld ),使用防火墙(iptables)
  4. 安装lua和openresty
  5. eclipse字体的设置
  6. 二模 (8) day1
  7. http://www.ruanyifeng.com/blog/2007/03/metadata.html
  8. python 基础——装饰器
  9. Windows Phone 动态改变ListBox样式
  10. java反射机制初探
  11. PHP trait
  12. jOOR
  13. “数学口袋精灵”App的第二个Sprint计划----开发日记
  14. 第23章 RTX 低功耗之待机模式
  15. zabbix分布式系统监视
  16. 训练赛第二场C题 zoj 2339 Hyperhuffman
  17. UNIX网络编程读书笔记:select函数
  18. zookeeper应用:屏障、队列、分布式锁
  19. linux系统下部署war包
  20. [leetcode-655-Print Binary Tree]

热门文章

  1. React Native 混合开发与实现
  2. Java 操作Word书签(一):添加、删除、读取书签
  3. Spring Cloud Gateway 服务网关快速上手
  4. caddy(四)Run详解
  5. Socket通信封装MIna框架--含羞代放
  6. 原生js实现的一个随机颜色的简单效果
  7. Nginx总结(二)基于ip的虚拟主机配置
  8. Django--路由层、伪静态页面、虚拟环境、视图层
  9. 关于post和get的区别
  10. Elasticsearch核心技术(2)--- 基本概念(Index、Type、Document、集群、节点、分片及副本、倒排索引)