网站首页 > 资源文章 正文
本文一共分三部分:SpringBoot+Mybatis环境搭建、两种方式配置多数据源、两种方式实现跨数据源事务,您可以直接跳到喜欢的部分,不过按顺序看完也不会花很多时间。。。
一、搭建SpringBoot+Mybatis框架环境
1、引入依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
2、填写配置
spring:
datasource:
username: test
password: test
url: jdbc:mysql://jiubugaosuni.com:8888/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
3、建立mapper接口及配置Mybatis扫描包
package cn.zhh.mapper;
import cn.zhh.entity.Student;
/**
* 学生Mapper
*
* @author Zhou Huanghua
* @date 2019/10/25 23:09
*/
public interface StudentMapper {
/**
* 插入一条学生记录
*
* @param student 学生信息
* @return 插入数量
*/
int insert(Student student);
/**
* 根据id删除学生记录
*
* @param id 学生id
* @return 删除数量
*/
int deleteById(Long id);
}
4、Mapper.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.zhh.mapper.StudentMapper">
<resultMap id="BaseResultMap" type="cn.zhh.entity.Student">
<result column="id" jdbcType="BIGINT" property="id"/>
<result column="name" jdbcType="VARCHAR" property="name"/>
<result column="code" jdbcType="VARCHAR" property="code"/>
<result column="sex" jdbcType="TINYINT" property="sex"/>
<result column="create_time" jdbcType="DATE" property="createTime"/>
<result column="last_update_time" jdbcType="DATE" property="lastUpdateTime"/>
<result column="is_deleted" jdbcType="TINYINT" property="isDeleted"/>
</resultMap>
<insert id="insert" parameterType="cn.zhh.entity.Student">
INSERT INTO student (`name`, `code`, `sex`) VALUES (#{name, jdbcType=VARCHAR}, #{code, jdbcType=VARCHAR}, #{sex, jdbcType=TINYINT})
</insert>
<delete id="deleteById" parameterType="java.lang.Long">
DELETE FROM student WHERE id = #{id, jdbcType=BIGINT}
</delete>
</mapper>
二、两种方式配置多数据源
1、动态切换数据源
2、不同的mapper接口包使用不同的数据源
spring:
datasource:
username: test
password: test
url: jdbc:mysql://jiubugaosuni.com:8888/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
datasource2:
username: test2
password: test2
url: jdbc:mysql://biexiangzhidao.net:6666/test2?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
/**
* 数据源配置
*
* @author Zhou Huanghua
* @date 2019/10/26 0:24
*/
@Configuration
public class DataSourceConfig {
@Bean
@Primary
public DataSource dataSource(@Value("${spring.datasource.username}") String username,
@Value("${spring.datasource.password}") String password,
@Value("${spring.datasource.url}") String url,
@Value("${spring.datasource.driver-class-name}") String driverClassName) {
return createDataSource(username, password, url, driverClassName);
}
@Bean
public DataSource dataSource2(@Value("${spring.datasource2.username}") String username,
@Value("${spring.datasource2.password}") String password,
@Value("${spring.datasource2.url}") String url,
@Value("${spring.datasource2.driver-class-name}") String driverClassName) {
return createDataSource(username, password, url, driverClassName);
}
private DataSource createDataSource(String username, String password, String url, String driverClassName) {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setJdbcUrl(url);
dataSource.setDriverClassName(driverClassName);
return dataSource;
}
}
/**
* MybatisConfig配置类
*
* @author Zhou Huanghua
* @date 2019/10/26 0:31
*/
public class MybatisConfig {
@Configuration
@MapperScan(
basePackages = "cn.zhh.mapper",
sqlSessionTemplateRef = "sqlSessionTemplate")
public static class Db1 {
@Bean
@Primary
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
return factoryBean.getObject();
}
@Bean
@Primary
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
@Bean
@Primary
public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("dataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
@Configuration
@MapperScan(
basePackages = "cn.zhh.mapper2",
sqlSessionTemplateRef = "sqlSessionTemplate2")
public static class Db2 {
@Bean
public SqlSessionFactory sqlSessionFactory2(@Qualifier("dataSource2") DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
return factoryBean.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplate2(@Qualifier("sqlSessionFactory2") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
@Bean
public DataSourceTransactionManager dataSourceTransactionManager2(@Qualifier("dataSource2") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
}
三、两种方式实现跨数据源事务
1、atomikos
2、注解+切面 = 自己实现
/**
* 多数据源事务注解
*
* @author Zhou Huanghua
* @date 2019/10/26 1:16
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MultiDataSourceTransactional {
/**
* 事务管理器数组
*/
String[] transactionManagers();
}
/**
* 多数据源事务切面
* ※采用Around似乎不行※
*
* @author Zhou Huanghua
* @date 2019/10/26 1:16
*/
@Component
@Aspect
public class MultiDataSourceTransactionAspect {
/**
* 线程本地变量:为什么使用栈?※为了达到后进先出的效果※
*/
private static final ThreadLocal<Stack<Pair<DataSourceTransactionManager, TransactionStatus>>> THREAD_LOCAL = new ThreadLocal<>();
/**
* 用于获取事务管理器
*/
@Autowired
private ApplicationContext applicationContext;
/**
* 事务声明
*/
private DefaultTransactionDefinition def = new DefaultTransactionDefinition();
{
// 非只读模式
def.setReadOnly(false);
// 事务隔离级别:采用数据库的
def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
// 事务传播行为
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
}
/**
* 切面
*/
@Pointcut("@annotation(cn.zhh.annotation.MultiDataSourceTransactional)")
public void pointcut() {
}
/**
* 声明事务
*
* @param transactional 注解
*/
@Before("pointcut() && @annotation(transactional)")
public void before(MultiDataSourceTransactional transactional) {
// 根据设置的事务名称按顺序声明,并放到ThreadLocal里
String[] transactionManagerNames = transactional.transactionManagers();
Stack<Pair<DataSourceTransactionManager, TransactionStatus>> pairStack = new Stack<>();
for (String transactionManagerName : transactionManagerNames) {
DataSourceTransactionManager transactionManager = applicationContext.getBean(transactionManagerName, DataSourceTransactionManager.class);
TransactionStatus transactionStatus = transactionManager.getTransaction(def);
pairStack.push(new Pair(transactionManager, transactionStatus));
}
THREAD_LOCAL.set(pairStack);
}
/**
* 提交事务
*/
@AfterReturning("pointcut()")
public void afterReturning() {
// ※栈顶弹出(后进先出)
Stack<Pair<DataSourceTransactionManager, TransactionStatus>> pairStack = THREAD_LOCAL.get();
while (!pairStack.empty()) {
Pair<DataSourceTransactionManager, TransactionStatus> pair = pairStack.pop();
pair.getKey().commit(pair.getValue());
}
THREAD_LOCAL.remove();
}
/**
* 回滚事务
*/
@AfterThrowing(value = "pointcut()")
public void afterThrowing() {
// ※栈顶弹出(后进先出)
Stack<Pair<DataSourceTransactionManager, TransactionStatus>> pairStack = THREAD_LOCAL.get();
while (!pairStack.empty()) {
Pair<DataSourceTransactionManager, TransactionStatus> pair = pairStack.pop();
pair.getKey().rollback(pair.getValue());
}
THREAD_LOCAL.remove();
}
}
猜你喜欢
- 2024-09-26 如何避免重复提交?分布式服务的幂等性设计
- 2024-09-26 聊聊如何实现一个带幂等模板的Kafka消费者
- 2024-09-26 Docker 安装 Kibana(DOCKER 安装UNTUNTU 图形界面 装不上)
- 2024-09-26 「优雅代码」03-optional杜绝空指针异常
- 2024-09-26 Mybatis plus通用字段自动填充的最佳实践总结
- 2024-09-26 不吹牛逼,撸个注解有什么难的(切记不吹牛)
- 2024-09-26 ElasticSearch入门一:入门安装和索引基本操作
- 2024-09-26 如何优雅地记录操作日志?(如何优雅地记录操作日志)
- 2024-09-26 使用Java8改造出来的模板方法真的是yyds
- 2024-09-26 java利用枚举与数据库交互(java利用枚举与数据库交互方式)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- 电脑显示器花屏 (79)
- 403 forbidden (65)
- linux怎么查看系统版本 (54)
- 补码运算 (63)
- 缓存服务器 (61)
- 定时重启 (59)
- plsql developer (73)
- 对话框打开时命令无法执行 (61)
- excel数据透视表 (72)
- oracle认证 (56)
- 网页不能复制 (84)
- photoshop外挂滤镜 (58)
- 网页无法复制粘贴 (55)
- vmware workstation 7 1 3 (78)
- jdk 64位下载 (65)
- phpstudy 2013 (66)
- 卡通形象生成 (55)
- psd模板免费下载 (67)
- shift (58)
- localhost打不开 (58)
- 检测代理服务器设置 (55)
- frequency (66)
- indesign教程 (55)
- 运行命令大全 (61)
- ping exe (64)
本文暂时没有评论,来添加一个吧(●'◡'●)