溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

springboot中怎么利用mybatis-plus 配置多數據源

發布時間:2021-06-22 16:19:21 來源:億速云 閱讀:580 作者:Leah 欄目:編程語言
# SpringBoot中怎么利用MyBatis-Plus配置多數據源

## 前言

在現代企業級應用開發中,多數據源的需求變得越來越普遍。無論是讀寫分離、分庫分表,還是需要同時訪問多個不同類型的數據庫,多數據源配置都成為了開發者必須掌握的技能。MyBatis-Plus作為MyBatis的增強工具,在多數據源場景下提供了簡潔高效的解決方案。本文將詳細介紹在SpringBoot項目中如何利用MyBatis-Plus配置和使用多數據源。

## 一、多數據源應用場景

### 1.1 常見使用場景

- **讀寫分離**:主庫負責寫操作,從庫負責讀操作
- **分庫分表**:數據水平拆分到不同數據庫實例
- **多租戶系統**:每個租戶使用獨立的數據源
- **異構數據庫**:同時訪問MySQL、Oracle等不同數據庫

### 1.2 技術選型對比

| 方案               | 優點                          | 缺點                          |
|--------------------|-----------------------------|-----------------------------|
| 原生JDBC           | 靈活性強                    | 代碼冗余,維護成本高          |
| Spring AbstractRoutingDataSource | 與Spring集成好       | 需要自行實現路由邏輯          |
| MyBatis-Plus多數據源 | 配置簡單,功能完善          | 需要引入額外依賴              |

## 二、環境準備

### 2.1 項目依賴

```xml
<!-- Spring Boot Starter -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- MyBatis-Plus Starter -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
</dependency>

<!-- 多數據源核心依賴 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.6.1</version>
</dependency>

<!-- 數據庫驅動 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

<!-- 其他工具 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

2.2 數據庫準備

準備兩個數據庫實例,本文示例使用: - 主庫:ds1 (端口3306) - 從庫:ds2 (端口3307)

三、基礎配置

3.1 配置文件

application.yml 配置示例:

spring:
  datasource:
    dynamic:
      primary: master # 設置默認數據源
      strict: false  # 是否嚴格匹配數據源
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/ds1?useSSL=false&serverTimezone=UTC
          username: root
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave:
          url: jdbc:mysql://localhost:3307/ds2?useSSL=false&serverTimezone=UTC
          username: root
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver

3.2 數據源配置類

@Configuration
@MapperScan(basePackages = "com.example.mapper")
public class DataSourceConfig {
    
    /**
     * 無需@Bean注解,dynamic-datasource會自動配置
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 分頁插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

四、多數據源使用方式

4.1 注解方式切換數據源

@DS 注解使用

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    
    // 默認使用主數據源
    @Override
    public User getMasterUser(Long id) {
        return userMapper.selectById(id);
    }
    
    // 指定從數據源
    @DS("slave")
    @Override
    public User getSlaveUser(Long id) {
        return userMapper.selectById(id);
    }
}

注解作用范圍

  • 方法級別:優先級最高
  • 類級別:類中所有方法默認使用該數據源
  • 接口級別:接口實現類默認使用該數據源

4.2 編程式切換數據源

public class DataSourceContextHolder {
    
    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
    
    public static void setDataSource(String dsName) {
        CONTEXT_HOLDER.set(dsName);
    }
    
    public static String getDataSource() {
        return CONTEXT_HOLDER.get();
    }
    
    public static void clearDataSource() {
        CONTEXT_HOLDER.remove();
    }
}

// 使用示例
public List<User> getAllUsers() {
    try {
        DataSourceContextHolder.setDataSource("slave");
        return userMapper.selectList(null);
    } finally {
        DataSourceContextHolder.clearDataSource();
    }
}

五、高級特性配置

5.1 多數據源事務管理

@Service
public class OrderService {
    
    @DS("master")
    @Transactional
    public void createOrder(Order order) {
        // 主庫操作
        orderMapper.insert(order);
        
        // 切換數據源需要新開事務
        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
        transactionTemplate.execute(status -> {
            try {
                DataSourceContextHolder.setDataSource("slave");
                // 從庫操作
                logMapper.insertLog(order);
                return true;
            } finally {
                DataSourceContextHolder.clearDataSource();
            }
        });
    }
}

5.2 動態添加數據源

@Autowired
private DynamicRoutingDataSource dynamicRoutingDataSource;

public void addNewDataSource(String dsName, DataSourceProperty property) {
    DataSource dataSource = dynamicDataSourceCreator.createDataSource(property);
    dynamicRoutingDataSource.addDataSource(dsName, dataSource);
}

5.3 多租戶數據源隔離

public class TenantDataSourceSelector {
    
    public static String determineCurrentLookupKey() {
        // 從當前線程獲取租戶信息
        String tenantId = TenantContext.getCurrentTenant();
        return "tenant_" + tenantId;
    }
}

// 配置類添加
@Bean
public AbstractRoutingDataSource multiTenantDataSource() {
    DynamicRoutingDataSource ds = new DynamicRoutingDataSource();
    ds.setDataSourceSelector(TenantDataSourceSelector::determineCurrentLookupKey);
    return ds;
}

六、性能優化建議

6.1 連接池配置

spring:
  datasource:
    dynamic:
      datasource:
        master:
          hikari:
            maximum-pool-size: 20
            minimum-idle: 5
            connection-timeout: 30000
            idle-timeout: 600000
            max-lifetime: 1800000

6.2 多數據源監控

@RestController
@RequestMapping("/datasource")
public class DataSourceMonitorController {
    
    @Autowired
    private DynamicRoutingDataSource dynamicRoutingDataSource;
    
    @GetMapping("/stats")
    public Map<String, Object> getDataSourceStats() {
        Map<String, DataSource> dataSources = dynamicRoutingDataSource.getCurrentDataSources();
        Map<String, Object> stats = new HashMap<>();
        
        dataSources.forEach((name, ds) -> {
            if (ds instanceof HikariDataSource) {
                HikariDataSource hikari = (HikariDataSource) ds;
                stats.put(name, hikari.getHikariPoolMXBean());
            }
        });
        
        return stats;
    }
}

七、常見問題解決方案

7.1 事務不生效問題

現象:跨數據源事務無法回滾
解決方案: 1. 使用JTA分布式事務 2. 采用最終一致性方案 3. 拆分業務邏輯,避免跨庫事務

7.2 數據源切換失敗

排查步驟: 1. 檢查@DS注解是否被AOP代理 2. 確認數據源名稱拼寫正確 3. 檢查是否配置了strict模式

7.3 連接泄漏問題

預防措施: 1. 確保每次操作后清理ThreadLocal 2. 使用try-finally代碼塊 3. 配置合理的連接超時時間

八、完整示例代碼

8.1 實體類

@Data
@TableName("t_user")
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

8.2 Mapper接口

public interface UserMapper extends BaseMapper<User> {
    
    @DS("slave")
    @Select("SELECT * FROM t_user WHERE age > #{age}")
    List<User> selectUsersByAge(@Param("age") Integer age);
}

8.3 測試Controller

@RestController
@RequestMapping("/user")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @GetMapping("/master/{id}")
    public User getFromMaster(@PathVariable Long id) {
        return userService.getMasterUser(id);
    }
    
    @GetMapping("/slave/{id}")
    public User getFromSlave(@PathVariable Long id) {
        return userService.getSlaveUser(id);
    }
}

九、總結

本文詳細介紹了在SpringBoot項目中整合MyBatis-Plus實現多數據源配置的全過程,包括:

  1. 基礎環境搭建和依賴配置
  2. 多種數據源切換方式(注解/編程式)
  3. 高級特性如動態數據源、多租戶支持
  4. 性能優化和問題排查方案

MyBatis-Plus的多數據源方案相比原生實現具有明顯優勢:

  • 配置簡單:通過注解即可完成數據源切換
  • 功能完善:內置連接池管理、監控等功能
  • 擴展性強:支持動態增減數據源

在實際項目中,建議根據具體業務場景選擇合適的多數據源策略,并注意事務管理和連接泄漏問題。對于更復雜的分布式事務場景,可以考慮集成Seata等分布式事務框架。

附錄

A. 推薦閱讀

B. 版本說明

  • SpringBoot: 2.7.x
  • MyBatis-Plus: 3.5.3
  • dynamic-datasource: 3.6.1

C. 示例項目

完整示例代碼已上傳至GitHub: springboot-mybatisplus-multi-ds-demo “`

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女