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。

相关推荐
弗拉唐2 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
凌冰_3 小时前
IDEA2023 SpringBoot整合MyBatis(三)
spring boot·后端·mybatis
Elaine2023915 小时前
零碎04 MybatisPlus自定义模版生成代码
java·spring·mybatis
一二小选手5 小时前
【MyBatis】全局配置文件—mybatis.xml 创建xml模板
xml·java·mybatis
刘大浪6 小时前
后端数据增删改查基于Springboot+mybatis mysql 时间根据当时时间自动填充,数据库连接查询不一致,mysql数据库连接不好用
数据库·spring boot·mybatis
蓝染-惣右介8 小时前
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
java·数据库·tomcat·mybatis
武子康9 小时前
Java-07 深入浅出 MyBatis - 一对多模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据库·sql·mybatis·springboot
一二小选手9 小时前
【Mybatis】@Param注解 resultMap手动映射
java·mybatis
郑祎亦12 小时前
Spring Boot 项目 myblog 整理
spring boot·后端·java-ee·maven·mybatis