springboot+dynamic多数据源配置

springboot+dynamic多数据源配置

dynamic-datasource-spring-boot-starter 是一个基于springboot的快速集成多数据源的启动器。

一、配置

  • pom引入
<dependency>
<groupId>com.baomidou</groupId>   
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>${version}</version        
</dependency>

示例:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.1.1</version>
</dependency>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>2.5.4</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.18</version>
</dependency>

 

配置数据源

spring:
  datasource:
  # 可以先在这里配置好通用的配置,比如
    druid:
      initial-size: 10
      max-active: 100
      min-idle: 3
      max-wait: 5000
      pool-prepared-statements: true
      max-pool-prepared-statement-per-connection-size: 100
    #dynamic开始多数据源配置
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      datasource:
        master:  # 数据源的名字:master
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
        slave_1:   # 数据源的名字:slave_1
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
        slave_2:
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://xx.xx.xx.xx:3308/dynamic
       #......省略
       #以上会配置一个默认库master,一个组slave下有两个子库slave_1,slave_2

主类修改

import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
/**
*修改主类的SpringBootApplication注解
*mybatisplus配置动态数据源时,切记需要关闭自带的自动数据源配置
**/
@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class) 

二、使用

使用@DS切换数据源。

@DS可以注解在方法上和类上,同时存在方法注解优先于类上注解。

免去了sql工厂的配置,直接使用@DS就可以注明是哪个数据源,超级方便,mybatis这种直接配置到Mapper层即可。

注解结果
没有@DS默认数据源
@DS("dsName")dsName可以为组名也可以为具体某个库的名称
@Service
@DS("slave_2")
public class UserServiceImpl implements UserService {

  @Autowired
  private JdbcTemplate jdbcTemplate;

  public List<Map<String, Object>> selectAll() {
    return  jdbcTemplate.queryForList("select * from user");
  }
  @Override
  @DS("slave_1")
  public List<Map<String, Object>> selectByCondition() {
    return  jdbcTemplate.queryForList("select * from user where age >10");
  }
}

官方地址:https://mp.baomidou.com/guide/dynamic-datasource.html

三、 多数据源事务控制

使用@DSTransactional

示例:

public class OrderService {

    private final OrderMapper orderMapper;
    private final AccountService accountService;
    private final ProductService productService;

    @DSTransactional
    public void placeOrder(PlaceOrderRequest request) {
        log.info("=============ORDER START=================");
        Long userId = request.getUserId();
        Long productId = request.getProductId();
        Integer amount = request.getAmount();
        log.info("收到下单请求,用户:{}, 商品:{},数量:{}", userId, productId, amount);

        log.info("当前 XID: {}", TransactionContext.getXID());

        Order order = Order.builder()
                .userId(userId)
                .productId(productId)
                .status(OrderStatus.INIT)
                .amount(amount)
                .build();

        orderMapper.insert(order);
        log.info("订单一阶段生成,等待扣库存付款中");
        // 扣减库存并计算总价
        Double totalPrice = productService.reduceStock(productId, amount);
        // 扣减余额
        accountService.reduceBalance(userId, totalPrice);

        order.setStatus(OrderStatus.SUCCESS);
        order.setTotalPrice(totalPrice);
        orderMapper.updateById(order);
        log.info("订单已成功下单");
        log.info("=============ORDER END=================");
    }
}

public class ProductService {

    private final ProductMapper productMapper;

    @DS("product")
    public Double reduceStock(Long productId, Integer amount) {
        log.info("=============PRODUCT START=================");
        log.info("当前 XID: {}", TransactionContext.getXID());

        // 检查库存
        Product product = productMapper.selectById(productId);
        Assert.notNull(product, "商品不存在");
        Integer stock = product.getStock();
        log.info("商品编号为 {} 的库存为{},订单商品数量为{}", productId, stock, amount);

        if (stock < amount) {
            log.warn("商品编号为{} 库存不足,当前库存:{}", productId, stock);
            throw new RuntimeException("库存不足");
        }
        log.info("开始扣减商品编号为 {} 库存,单价商品价格为{}", productId, product.getPrice());
        // 扣减库存
        int currentStock = stock - amount;
        product.setStock(currentStock);
        productMapper.updateById(product);
        double totalPrice = product.getPrice() * amount;
        log.info("扣减商品编号为 {} 库存成功,扣减后库存为{}, {} 件商品总价为 {} ", productId, currentStock, amount, totalPrice);
        log.info("=============PRODUCT END=================");
        return totalPrice;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个比较具体的技术问题。首先,Spring Boot可以通过配置多个数据源来实现多数据源的切换。其次,可以使用AOP技术,在方法执行前动态切换数据源。以下是一些关键的代码片段: 1. 在application.properties文件中配置多个数据源 ``` spring.datasource.primary.url=jdbc:mysql://localhost:3306/db1 spring.datasource.primary.username=user1 spring.datasource.primary.password=pass1 spring.datasource.secondary.url=jdbc:mysql://localhost:3306/db2 spring.datasource.secondary.username=user2 spring.datasource.secondary.password=pass2 ``` 2. 创建多个数据源的Bean ``` @Configuration public class DataSourceConfig { @Bean(name = "primaryDataSource") @ConfigurationProperties(prefix = "spring.datasource.primary") public DataSource primaryDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "secondaryDataSource") @ConfigurationProperties(prefix = "spring.datasource.secondary") public DataSource secondaryDataSource() { return DataSourceBuilder.create().build(); } } ``` 3. 创建动态数据源并设置默认数据源 ``` @Configuration public class DynamicDataSourceConfig { @Autowired @Qualifier("primaryDataSource") private DataSource primaryDataSource; @Autowired @Qualifier("secondaryDataSource") private DataSource secondaryDataSource; @Bean(name = "dynamicDataSource") public DataSource dynamicDataSource() { DynamicDataSource dynamicDataSource = new DynamicDataSource(); Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put(DataSourceType.PRIMARY.name(), primaryDataSource); targetDataSources.put(DataSourceType.SECONDARY.name(), secondaryDataSource); dynamicDataSource.setTargetDataSources(targetDataSources); dynamicDataSource.setDefaultTargetDataSource(primaryDataSource); return dynamicDataSource; } @Bean public JdbcTemplate jdbcTemplate() { return new JdbcTemplate(dynamicDataSource()); } } ``` 4. 创建AOP切面,在方法执行前根据注解切换数据源 ``` @Aspect @Component public class DataSourceAspect { @Autowired @Qualifier("dynamicDataSource") private DataSource dynamicDataSource; @Pointcut("@annotation(com.example.demo.datasource.DataSource)") public void dataSourcePointCut() {} @Before("dataSourcePointCut()") public void before(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); DataSource dataSource = signature.getMethod().getAnnotation(DataSource.class); if (dataSource != null) { DataSourceType dataSourceType = dataSource.value(); DynamicDataSourceContextHolder.setDataSourceType(dataSourceType.name()); } } @After("dataSourcePointCut()") public void after(JoinPoint joinPoint) { DynamicDataSourceContextHolder.clearDataSourceType(); } } ``` 5. 在需要切换数据源的方法上添加注解 ``` @DataSource(DataSourceType.SECONDARY) public List<User> listUsers() { return jdbcTemplate.query("SELECT * FROM user", new BeanPropertyRowMapper<>(User.class)); } ``` 这样就可以实现动态切换多数据源了。希望能够帮到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值