Fork me on GitHub

dynamic-datasource多数据源

dynamic-datasource多数据源

请求 → AOP 拦截 → 动态切换 → Druid 连接池 → Mapper 执行 SQL
https://baomidou.com/guides/dynamic-datasource/

pom.xml引入

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.5.0</version>
</dependency>

application.yml数据源配置

spring:
  datasource:
    dynamic:
      primary: master
      strict: false
      datasource:
        master:
          url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
        slave_1:
          url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
        slave_2:
          url: ENC(xxxxx)
          username: ENC(xxxxx)
          password: ENC(xxxxx)
          driver-class-name: com.mysql.jdbc.Driver

使用@DS切换数据源

jdbcTemplate使用多数据源

@Service
@DS("slave")
public class UserServiceImpl implements UserService {

  @Autowired
  private JdbcTemplate jdbcTemplate;

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

Service层切换数据源

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @DS("slave_1")  // 使用slave_1数据源
    public List<User> getPrimaryUsers() {
        return userMapper.selectList(null);
    }

    @DS("slave_2")  // 使用slave_2数据源
    public List<User> getSecondaryUsers() {
        return userMapper.selectList(null);
    }
}

Mapper层切换数据源

@DS("slave_2")
@Mapper
public interface SecondaryUserMapper extends BaseMapper<User> {
    // 这个 Mapper 始终使用 slave_2 数据源
}

事务层切换数据源

@Transactional  // 默认事务在默认数据源
@DS("slave_1")
public void updateSecondaryUser(User user) {
    userMapper.updateById(user);
}

使用JdbcTemplate

  1. 切换数据源:DynamicDataSourceContextHolder.push("slave")
  2. 清理上下文:操作完成后 DynamicDataSourceContextHolder.clear(),避免后续 SQL 仍然跑在 slave 上。
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;

@Service
public class SlaveJdbcService {

    private final DataSource dataSource;

    public SlaveJdbcService(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public void createTable(String tableName) {
        String sql = String.format("CREATE TABLE IF NOT EXISTS %s LIKE dev_log", tableName);

        try {
            // 切换到 slave 数据源
            DynamicDataSourceContextHolder.push("slave");

            // 使用 JdbcTemplate 执行 SQL
            JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
            jdbcTemplate.execute(sql);

            System.out.println("在 slave 库中成功创建表: " + tableName);
        } finally {
            // 清理上下文,避免污染后续请求
            DynamicDataSourceContextHolder.clear();
        }
    }
}

使用场景:
•建表、DDL 等必须指定库的操作;
•特殊情况下,需要 强制路由到 slave(而不是默认的 master)。但如果只是普通的读写分离查询,推荐直接用 @DS("slave") 注解在方法或类上,代码更优雅。

posted @ 2025-08-25 19:58  秋夜雨巷  阅读(57)  评论(0)    收藏  举报