springbootdruidmybatismysql多数据源事务管理
springboot+druid+mybatis+mysql+多数据源事务管理
分布式事务在java中的解决方案就是JTA(即Java Transaction API);springboot官方提供了 Atomikos or Bitronix的解决思路;其实,大多数情况下很多公司是使用消息队列的方式实现分布式事务。这里分享的是Atomikos 的简单事务管理。
项目依赖
pom.xml中添加atomikos的springboot相关依赖:
<!--分布式事务管理器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!--这里最好要5.1.47之后的版本-->
<version>5.1.47</version>
</dependency>
application.properties配置文件中数据库相关信息:
#数据库1
spring.datasource.druid.one.url=jdbc:mysql://localhost:3306/test01?useUnicode=true&characterEncoding=utf-8
spring.datasource.druid.one.username=root
spring.datasource.druid.one.password=123456
#数据库2
spring.datasource.druid.two.url=jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8
spring.datasource.druid.two.username=root
spring.datasource.druid.two.password=123456
创建两个java配置类,分别读取上面的两个数据库相关信息:
@ConfigurationProperties(prefix = "spring.datasource.druid.one")
public class DsOneProperties {
private String username;
private String password;
private String url;
//这里省掉Set和get方法
}
@ConfigurationProperties(prefix = "spring.datasource.druid.two")
public class DsTwoProperties {
private String username;
private String password;
private String url;
//这里省掉Set和get方法
}
在SpringBoot项目启动类加上注解,启动时,就加载相关信息
@EnableConfigurationProperties(value = {DsOneProperties.class, DsTwoProperties.class})
创建主数据库配置类MyBatisConfigOne :
@Configuration//声明该类是一个配置类
@MapperScan(basePackages = "com.lwh.mybatistest.mapper", sqlSessionFactoryRef = "sqlSessionFactory1", sqlSessionTemplateRef = "sqlSessionTemplate1")
//扫描的包是com.lwh.mybatistest.mapper
public class MyBatisConfigOne {
// 配置主数据源
@Primary
@Bean
public DataSource dsOne(DsOneProperties dsOneProperties) throws SQLException {
//配置XA协议数据源,从配置文件中读取相应属性
MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
mysqlXaDataSource.setUrl(dsOneProperties.getUrl());
mysqlXaDataSource.setPassword(dsOneProperties.getPassword());
mysqlXaDataSource.setUser(dsOneProperties.getUsername());
//将本地事务注册到Atomikos全局事务
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName("dsOne");
return xaDataSource;
}
<span class="hljs-meta">@Primary</span>
<span class="hljs-meta">@Bean</span>(name = <span class="hljs-string">"sqlSessionFactory1"</span>)
<span class="hljs-function"><span class="hljs-keyword">public</span> SqlSessionFactory <span class="hljs-title">SqlSessionFactory1</span><span class="hljs-params">(@Qualifier(<span class="hljs-string">"dsOne"</span>)</span> DataSource dataSource)
<span class="hljs-keyword">throws</span> Exception </span>{
SqlSessionFactoryBean bean = <span class="hljs-keyword">new</span> SqlSessionFactoryBean();
bean.setDataSource(dataSource);
<span class="hljs-keyword">return</span> bean.getObject();
}
<span class="hljs-meta">@Primary</span>
<span class="hljs-meta">@Bean</span>(name = <span class="hljs-string">"sqlSessionTemplate1"</span>)
<span class="hljs-function"><span class="hljs-keyword">public</span> SqlSessionTemplate <span class="hljs-title">SqlSessionTemplate1</span><span class="hljs-params">(
@Qualifier(<span class="hljs-string">"sqlSessionFactory1"</span>)</span> SqlSessionFactory sqlSessionFactory) <span class="hljs-keyword">throws</span> Exception </span>{
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> SqlSessionTemplate(sqlSessionFactory);
}
}
依照上面主数据库配置类,创建从数据库配置类:
@Configuration
@MapperScan(basePackages = "com.lwh.mybatistest.mapper2", sqlSessionFactoryRef = "sqlSessionFactory2", sqlSessionTemplateRef = "sqlSessionTemplate2")
public class MyBatisConfigTwo {
@Bean
public DataSource dsTwo(DsTwoProperties dsTwoProperties) throws SQLException {
//配置从数据源
//配置XA协议数据源,从配置文件中读取相应属性
MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
mysqlXaDataSource.setUrl(dsTwoProperties.getUrl());
mysqlXaDataSource.setPassword(dsTwoProperties.getPassword());
mysqlXaDataSource.setUser(dsTwoProperties.getUsername());
//将本地事务注册到Atomikos全局事务
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName("dsTwo");
return xaDataSource;
}
<span class="hljs-meta">@Bean</span>(name = <span class="hljs-string">"sqlSessionFactory2"</span>)
<span class="hljs-function"><span class="hljs-keyword">public</span> SqlSessionFactory <span class="hljs-title">SqlSessionFactory2</span><span class="hljs-params">(@Qualifier(<span class="hljs-string">"dsTwo"</span>)</span> DataSource dataSource)
<span class="hljs-keyword">throws</span> Exception </span>{
SqlSessionFactoryBean bean = <span class="hljs-keyword">new</span> SqlSessionFactoryBean();
bean.setDataSource(dataSource);
<span class="hljs-keyword">return</span> bean.getObject();
}
<span class="hljs-meta">@Bean</span>(name = <span class="hljs-string">"sqlSessionTemplate2"</span>)
<span class="hljs-function"><span class="hljs-keyword">public</span> SqlSessionTemplate <span class="hljs-title">SqlSessionTemplate2</span><span class="hljs-params">(
@Qualifier(<span class="hljs-string">"sqlSessionFactory2"</span>)</span> SqlSessionFactory sqlSessionFactory) <span class="hljs-keyword">throws</span> Exception </span>{
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> SqlSessionTemplate(sqlSessionFactory);
}
}
创建一个简单的controller测试类:
@RestController
@RequestMapping("/book")
public class BookController {
@Autowired
BookService bookService;
<span class="hljs-meta">@Autowired</span>
BookService2 bookService2;
<span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/add1"</span>)
<span class="hljs-meta">@Transactional</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">addBook</span><span class="hljs-params">()</span> </span>{
Book book = <span class="hljs-keyword">new</span> Book();
book.setBookname(<span class="hljs-string">"测试"</span>);
book.setAuthor(<span class="hljs-string">"test:01"</span>);
System.out.println(<span class="hljs-string">"数据库1:>>>>"</span>);
bookService.addBook(book);
System.out.println(<span class="hljs-string">"数据库2:>>>>"</span>);
bookService2.addBook(book);
<span class="hljs-keyword">return</span> <span class="hljs-string">"测试add1操作成功!"</span>;
}
<span class="hljs-meta">@GetMapping</span>(<span class="hljs-string">"/add2"</span>)
<span class="hljs-meta">@Transactional</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">addBook2</span><span class="hljs-params">()</span> </span>{
Book book = <span class="hljs-keyword">new</span> Book();
book.setBookname(<span class="hljs-string">"测试add2"</span>);
book.setAuthor(<span class="hljs-string">"test:01"</span>);
System.out.println(<span class="hljs-string">"数据库1:>>>>"</span>);
bookService.addBook(book);
<span class="hljs-keyword">int</span> a = <span class="hljs-number">10</span> / <span class="hljs-number">0</span>;
System.out.println(<span class="hljs-string">"数据库2:>>>>"</span>);
bookService2.addBook(book);
<span class="hljs-keyword">return</span> <span class="hljs-string">"测试add2操作成功!"</span>;
}
}
Service类,就是简单的插入方法,调用mapper:
@Service
public class BookService {
<span class="hljs-meta">@Autowired</span>
BookMapper bookMapper;
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">addBook</span><span class="hljs-params">(Book book)</span> </span>{
bookMapper.insertSelective(book);
}
}
springboot默认有事务管理器,所以这里没有配置,使用默认的即可,如果有特别需求,可以自行创建自己的事务管理器。
最简单的atomikos插件的使用就配置完了,配置信息相对简单,想深入学习的同学,可以参考官方的文档。
分布式事务有多种主流形态,包括:
基于消息实现的分布式事务
基于补偿实现的分布式事务(gts/seata自动补偿的形式)
基于TCC实现的分布式事务
基于SAGA实现的分布式事务
基于2PC实现的分布式事务
之所以有这么多形态,是因为任何事情都没有银弹,只有最合适当前场景的解决方案。
springbootdruidmybatismysql多数据源事务管理的更多相关文章
- spring+springmvc+mybatis+oracle+atomikos+jta实现多数据源事务管理
---恢复内容开始--- 在做项目过程中,遇到了需要一个项目中访问两个数据库的情况,发现使用常规的spring管理事务,导致事务不能正常回滚,因此,采用了jta+atomikos的分布式数据源方式 ...
- springboot-jta-atomikos多数据源事务管理
背景 我们平时在用springboot开发时,要使用事务,只需要在方法上添加@Transaction注解即可,但这种方式只适用单数据源,在多数据源下就不再适用: 比如在多数据源下,我们在一个方法里执行 ...
- Spring中实现多数据源事务管理
文章转自 https://www.2cto.com/kf/201507/424229.html 前言 由于项目中引入了多个数据源,并且需要对多个数据源进行写操作,那么多数据源的事务管理自然成了不可避 ...
- Spring Boot2.0之多数据源事务管理
结合前面做的小项目,如果我把test01 test02下面的 service 都加了 事务的注解 这样启动时候会报错! 事务管理器里面不能有两个事务!!!! 这时候需要用 @Transactiona ...
- 二、spring集成ibatis进行数据源事务管理拦截器环境配置
1.dataSource-applicationContext.xml文件配置理解:(spring1.2.8+ibatis1.5.3)1.1)配置数据源 DriverManagerDataSource ...
- SpringBoot2 整合JTA组件,多数据源事务管理
本文源码:GitHub·点这里 || GitEE·点这里 一.JTA组件简介 1.JTA基本概念 JTA即Java-Transaction-API,JTA允许应用程序执行分布式事务处理,即在两个或多个 ...
- spring JTA多数据源事务管理详细教程
<context:annotation-config /> <!-- 使用注解的包路径 --> <context:component-scan base-package= ...
- spring boot 或 spring 集成 atomikos jta 完成多数据源事务管理
前言:对于事务,spring 不提供自己的实现,只是定义了一个接口来供其他厂商实现,具体些的请看我的这篇文章: https://www.cnblogs.com/qiaoyutao/p/11289996 ...
- [转]Spring3核心技术之事务管理机制
原文地址:http://chouyi.iteye.com/blog/1675199 Spring对事务的解决办法其实分为2种:编程式实现事务,AOP配置声明式解决方案. http://jinnians ...
随机推荐
- Neo4j
Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中.它是一个嵌入式的.基于磁盘的.具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做 ...
- jupyter lab 的基本使用
在创建一个文件即可 进入创建的文件,在创建一个ipynb文件即可操作 注意右上角必须是python3 可以哦(如果点了shutdown 就会没有内核 需要自己在定义python编辑器) jupyter ...
- Go-函数高级使用-条件分支-包管理-for循环-switch语句-数组及切片-与或非逻辑符
目录 科普 python 注释 # 函数高级 if else if else 包管理 下载第三方包 比较热门的框架 for 循环 for 循环的几种写法 switch 语句 数组及数组切片 数组迭代 ...
- 利用神器BTrace 追踪线上 Spring Boot应用运行时信息
概述 生产环境中的服务可能会出现各种问题,但总不能让服务下线来专门排查错误,这时候最好有一些手段来获取程序运行时信息,比如 接口方法参数/返回值.外部调用情况 以及 函数执行时间等信息以便定位问题.传 ...
- 创建web服务器
用node创建本地web服务 1,创建本地文件server.js var http = require('http'); var url=require('url'); var fs=require( ...
- 以太坊再爆高危漏洞!黑客增发ATN 1100万枚token事件始末
事情发生在5月中旬,ATN技术人员发现Token合约由于存在漏洞受到攻击.不过ATN基金会随后透露,将销毁1100万个ATN,并恢复ATN总量,同时将在主链上线映射时对黑客地址内的资产予以剔除,确保原 ...
- 使用Golang时遇到的一些坑
1. [致命]不是所有Panic都能捕获 我们知道Golang给开发人员提供recover()机制,对堆栈异常(panic)进行捕获并自定义其处理逻辑.下面举个例子: 构造一个除0的异常场景: 输出结 ...
- 10.自定义EL函数和自定义标签
需要在JSP页面中进行一些常见逻辑操作(如对字符串进行操作),首先考虑是否可以用到sun公司提供的EL函数库(fn.tld)和JSTL 核心标签库 如果sun公司的EL函数库没有或者无法满足,就需要自 ...
- sqlserver 2008修改数据库表的时候错误提示“阻止保存要求重新创建表的更改”
当用户在在SQL Server 2008企业管理器中更改表结构时,必须要先删除原来的表,然后重新创建新表,才能完成表的更改,如果强行更改会出现以下提示:不允许保存更改.您所做的更改要求删除并重新创建以 ...
- Linux 虚拟机扩容
由于在装软件,原来的20G空间不够使用,需要扩容操作. 1.关闭虚拟机 2.点击编辑虚拟机设置 选中硬盘,添加,硬盘,推荐,确定大小,完成. 2.启动虚拟机 查看磁盘使用情况: [root@maste ...