mybatis plus 配置多数据源(数据源进行切换)

多数据源( 数据源 进行切换)

AbstractRoutingDataSource 根据用户定义的规则选择当前的数据源,这样我们可以在执行查询之前,设置使用的数据源。实现可动态路由的数据源,在每次数据库查询操作前执行。它的抽象方法 determineCurrentLookupKey() 决定使用哪个数据源。

1、application.yml中配置多个数据源

# Order
spring.datasource.order.url =jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false
spring.datasource.order.username =root
spring.datasource.order.password =123456
spring.datasource.order.driver-class-name =com.mysql.cj.jdbc.Driver
# Storage
spring.datasource.storage.url =jdbc:mysql://localhost:3306/seata_storage?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false
spring.datasource.storage.username =root
spring.datasource.storage.password =123456
spring.datasource.storage.driver-class-name =com.mysql.cj.jdbc.Driver
# Pay
spring.datasource.pay.url =jdbc:mysql://localhost:3306/seata_pay?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false
spring.datasource.pay.username =root
spring.datasource.pay.password =123456
spring.datasource.pay.driver-class-name =com.mysql.cj.jdbc.Driver

2、主启动类添加注解

@SpringBootApplication

@MapperScan("com.example.demo.mapper" )

3、编写配置类

@Getter
public enum DataSourceKey {
/**
* Order data source key.
*/
ORDER ,
/**
* Storage data source key.
*/
STORAGE ,
/**
* Pay data source key.
*/
PAY ,
}

public class DynamicDataSourceContextHolder {
private static final ThreadLocal<String> CONTEXT_HOLDER = ThreadLocal.withInitial (DataSourceKey.ORDER ::name);
private static List<Object> dataSourceKeys = new ArrayList<>();
public static void setDataSourceKey(DataSourceKey key) {
CONTEXT_HOLDER .set(key.name());
}
public static String getDataSourceKey() {
return CONTEXT_HOLDER .get();
}
public static void clearDataSourceKey() {
CONTEXT_HOLDER .remove();
}
public static List<Object> getDataSourceKeys() {
return dataSourceKeys ;
}
}

public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
//log.info("当前数据源 [{}]", DynamicDataSourceContextHolder.getDataSourceKey());
return DynamicDataSourceContextHolder.getDataSourceKey ();
}
}

@Configuration
public class DataSourceProxyConfig {
@Bean("originOrder" )
@ConfigurationProperties(prefix = "spring.datasource.order" )
public DataSource dataSourceMaster() {
return new DruidDataSource();
}
@Bean("originStorage" )
@ConfigurationProperties(prefix = "spring.datasource.storage" )
public DataSource dataSourceStorage() {
return new DruidDataSource();
}
@Bean("originPay" )
@ConfigurationProperties(prefix = "spring.datasource.pay" )
public DataSource dataSourcePay() {
return new DruidDataSource();
}

@Bean(name = "order" )
public DataSourceProxy masterDataSourceProxy(@Qualifier("originOrder" ) DataSource dataSource) {
return new DataSourceProxy(dataSource);
}
@Bean(name = "storage" )
public DataSourceProxy storageDataSourceProxy(@Qualifier("originStorage" ) DataSource dataSource) {
return new DataSourceProxy(dataSource);
}
@Bean(name = "pay" )
public DataSourceProxy payDataSourceProxy(@Qualifier("originPay" ) DataSource dataSource) {
return new DataSourceProxy(dataSource);
}
@Bean("dynamicDataSource" )
public DataSource dynamicDataSource(@Qualifier("order" ) DataSource dataSourceOrder,
@Qualifier("storage" ) DataSource dataSourceStorage,
@Qualifier("pay" ) DataSource dataSourcePay) {
DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();
Map<Object, Object> dataSourceMap = new HashMap<>(3);
dataSourceMap.put(DataSourceKey.ORDER .name(), dataSourceOrder);
dataSourceMap.put(DataSourceKey.STORAGE .name(), dataSourceStorage);
dataSourceMap.put(DataSourceKey.PAY .name(), dataSourcePay);

dynamicRoutingDataSource.setDefaultTargetDataSource(dataSourceOrder);
dynamicRoutingDataSource.setTargetDataSources(dataSourceMap);
DynamicDataSourceContextHolder.getDataSourceKeys ().addAll(dataSourceMap.keySet());
return dynamicRoutingDataSource;
}
@Bean
@ConfigurationProperties(prefix = "mybatis-plus" ) // MybatisSqlSessionFactoryBean中有各种MybatisPlus的配置属性(globalConfig、mapper L ocations}SqlSessionFactoryBean中则是mybatis的各种配置属性(typeAlies 、mapper L ocations )
public MybatisSqlSessionFactoryBean sqlSessionFactoryBean(@Qualifier("dynamicDataSource" ) DataSource dataSource) {
// 这里用 MybatisSqlSessionFactoryBean 代替了 SqlSessionFactoryBean,否则 MyBatisPlus 不会生效
MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
mybatisSqlSessionFactoryBean.setDataSource(dataSource);
return mybatisSqlSessionFactoryBean;
}
}

调用切换数据源:

@GlobalTransactional
@Override
public OperationResponse placeOrder(PlaceOrderRequestVO placeOrderRequestVO) throws Exception {
DynamicDataSourceContextHolder. setDataSourceKey (DataSourceKey. ORDER ); //切换数据源
Integer amount = 1;
Integer price = placeOrderRequestVO.getPrice();
Order order = Order.builder ().build();
Integer saveOrderRecord = orderDao .insert(order);
// 扣减库存
boolean operationStorageResult = storageService .reduceStock(placeOrderRequestVO.getProductId(), amount);
// 扣减余额
boolean operationBalanceResult = payService .reduceBalance(placeOrderRequestVO.getUserId(), price);
DynamicDataSourceContextHolder. setDataSourceKey (DataSourceKey. ORDER ); //切换数据源
order.setStatus(OrderStatus.SUCCESS );
Integer updateOrderRecord = orderDao .updateById(order);
return success(operationStorageResult && operationBalanceResult);
}

项目启动报错: Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured

原因:导入spring-mybatis依赖后,springboot启动时会自动加载数据源,由于dataSource配置成多数据源加载不到spring.datasource.url故而报错。

解决:1、主启动类添加@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)

2、若上面配置还是无法解决,可以配置一个默认数据源让其启动时加载(不影响,会被多数据源切换时覆盖的):spring.datasource.url

额外:

SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(in);

SqlSession sqlSession=factory.openSession(); //sqlSession就是用来操作sql语句的

使用 MyBatis-Spring 之后, 会使用SqlSessionFactoryBean来代替SqlSessionFactoryBuilder创建SqlSessionFactory

MybatisPlus需要使用MybatisSqlSessionFactoryBean。

相关推荐
geBR OTTE5 小时前
SpringBoot(整合MyBatis + MyBatis-Plus + MyBatisX插件使用)
spring boot·tomcat·mybatis
Alfredorw7 小时前
Mybatis-Plus的使用
mybatis
Meepo_haha10 小时前
配置MyBatis-Plus打印执行的 SQL 语句到控制台或日志文件中
数据库·sql·mybatis
极创信息10 小时前
企业信创产品认证全流程:从信创适配到信创认证的实操指南(2026版)
java·数据库·spring boot·mysql·matlab·mybatis·软件工程
神舟之光13 小时前
Springboot+MyBatis-Plus连接MySQL初体验
spring boot·mysql·mybatis
Echo271713 小时前
mybatis的知识点总结
mybatis
小江的记录本1 天前
【注解】常见 Java 注解系统性知识体系总结(附《全方位对比表》+ 思维导图)
java·前端·spring boot·后端·spring·mybatis·web
小飞Coding1 天前
MyBatis Mapper 实现原理彻底解密——从动态代理到 JDBC 执行全链路剖析
后端·mybatis
华科易迅1 天前
MybatisPlus乐观锁
java·开发语言·mybatis
野犬寒鸦1 天前
Redis复习记录Day03
服务器·redis·后端·面试·bootstrap·mybatis