一、跨库事物失效的原因
- Spring@Transactional不支持跨数据源事物,Spring 事物控制是基于数据库链接进行的,当数据源切换后,数据库链接切换,事物回滚只能回退,当前持有的链接。
- Spring开启事物后,会将当前数据库及数据库链接资源进行线程绑定,导致数据源切换失效(数据源切换执行后,并未获取到新的数据库链接)。
二、解决方案
引入pom依赖
<!-- 数据源切换依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
package com.test.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
//数据源1
@DS("db1")
@Mapper
public interface Test1Dao {
@Update("update test1 set name = #{name} where id = #{id}")
void updateById(@Param("id")Integer id, @Param("name")String name);
}
package com.test.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.test.datasources.DataSourceNames;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
//数据源2
@DS(“db2”)
@Mapper
public interface Test2Dao {
@Update("update test2 set name = #{name} where id = #{id}")
void updateById(@Param("id")Integer id, @Param("name")String name);
}
package com.test.service;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.test.mapper.Test1Dao;
import com.test.mapper.Test2Dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class TestService {
@Autowired
private Test1Dao test1Dao;
@Autowired
private Test2Dao test2Dao;
/**
* 同一个数据源中的事务,都是数据源2
* 这里用的是spring的事务注解Transactional
* 这里必须加上注解多数据源注解@DS("db2"),否则使用的是默认数据源
*/
@DS("db2")
@Transactional
public void theSame() {
test2Dao.updateById(2,"第一次修改");
test2Dao.updateById(2,"第二次修改");
//这里报错回滚
int i = 1/0;
}
/**
* 多数据源中的事务,同时使用数据源1、2
* 如果这里用spring的事务注解Transactional,那么使用的是默认数据源
* 这里不需要加上注解@DS
*/
@DSTransactional
public void notAlike() {
test1Dao.updateById(1,"第一次修改");
test2Dao.updateById(2,"第二次修改");
//这里报错回滚
int i = 1/0;
}
}
© 版权声明
THE END
暂无评论内容