# MyBatis Plus 多数据源配置与使用文档 ## 1. 环境与依赖 ### 1.1 环境要求 - Spring Boot 3.x - MyBatis Plus 3.5.x - Java 21 ### 1.2 依赖添加 添加 MyBatis Plus 动态数据源依赖: ```xml com.baomidou dynamic-datasource-spring-boot-starter 3.6.1 ``` ## 2. 配置文件修改 ### 2.1 主配置文件 配置多数据源: ```yaml spring: datasource: dynamic: primary: master strict: false datasource: master: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://117.72.94.232:53306/tacit?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true username: root password: fU44GFH5 slave: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/tacit?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true username: root password: root123 ``` ### 2.2 配置说明 | 配置项 | 说明 | 示例值 | |-------|------|-------| | primary | 默认数据源名称 | master | | strict | 是否启用严格模式 | false | | datasource.master | 主数据源配置 | - | | datasource.slave | 从数据源配置 | - | | driver-class-name | 数据库驱动类名 | com.mysql.cj.jdbc.Driver | | url | 数据库连接地址 | jdbc:mysql://117.72.94.232:53306/tacit | | username | 数据库用户名 | root | | password | 数据库密码 | password | ## 3. 代码实现 ### 3.1 实体类 创建测试实体类 `TestEntity`: ```java package com.tacit.admin.entity; import com.baomidou.mybatisplus.annotation.TableName; import com.tacit.common.entity.Base; import lombok.Data; import lombok.EqualsAndHashCode; @Data @EqualsAndHashCode(callSuper = true) @TableName("test") // 指定数据库表名 public class TestEntity extends Base { @TableId(type = IdType.AUTO) private Long id; private String name; // 姓名 private Integer age; // 年龄 private String email; // 邮箱 } ``` ### 3.2 Mapper 接口 创建 Mapper 接口 `TestMapper`: ```java package com.tacit.admin.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.tacit.admin.entity.TestEntity; import org.apache.ibatis.annotations.Mapper; @Mapper // 标记为 MyBatis Mapper 接口 public interface TestMapper extends BaseMapper { // 继承 BaseMapper 后,自动拥有 CRUD 方法 } ``` ### 3.3 Service 接口 创建 Service 接口 `TestService`: ```java package com.tacit.admin.service; import com.baomidou.mybatisplus.extension.service.IService; import com.tacit.admin.entity.TestEntity; public interface TestService extends IService { /** * 根据 ID 查询测试数据 * @param id 主键 ID * @return TestEntity */ TestEntity getTestById(Long id); } ``` ### 3.4 Service 实现类 #### 3.4.1 主数据源实现类 创建主数据源 Service 实现类 `TestMasterServiceImpl`: ```java package com.tacit.admin.service.impl; import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.tacit.admin.entity.TestEntity; import com.tacit.admin.mapper.TestMapper; import com.tacit.admin.service.TestService; import org.springframework.stereotype.Service; @Service("testMasterService") // 指定 Bean 名称,方便注入 @DS("master") // 指定使用主数据源 public class TestMasterServiceImpl extends ServiceImpl implements TestService { /** * 使用主数据源查询数据 * @param id 主键 ID * @return TestEntity */ @Override public TestEntity getTestById(Long id) { return getById(id); // 调用父类方法,自动使用主数据源 } } ``` #### 3.4.2 从数据源实现类 创建从数据源 Service 实现类 `TestSlaveServiceImpl`: ```java package com.tacit.admin.service.impl; import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.tacit.admin.entity.TestEntity; import com.tacit.admin.mapper.TestMapper; import com.tacit.admin.service.TestService; import org.springframework.stereotype.Service; @Service("testSlaveService") // 指定 Bean 名称,方便注入 @DS("slave") // 指定使用从数据源 public class TestSlaveServiceImpl extends ServiceImpl implements TestService { /** * 使用从数据源查询数据 * @param id 主键 ID * @return TestEntity */ @Override public TestEntity getTestById(Long id) { return getById(id); // 调用父类方法,自动使用从数据源 } } ``` ### 3.5 控制器 创建测试控制器 `MultiDatasourceTestController`: ```java package com.tacit.admin.controller; import com.tacit.common.entity.ResponseResult; import com.tacit.admin.entity.TestEntity; import com.tacit.admin.service.TestService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/multi-datasource") @Tag(name = "多数据源测试接口", description = "用于测试多数据源的接口") public class MultiDatasourceTestController { @Autowired @Qualifier("testMasterService") // 注入主数据源 Service private TestService testMasterService; @Autowired @Qualifier("testSlaveService") // 注入从数据源 Service private TestService testSlaveService; @Operation(summary = "使用主数据源创建测试数据", description = "使用主数据源创建测试数据") @PostMapping("/master/create") public ResponseResult createTestDataWithMaster(@RequestBody TestEntity testEntity) { testMasterService.save(testEntity); // 使用主数据源保存数据 return ResponseResult.success(testEntity); } @Operation(summary = "使用主数据源查询测试数据", description = "使用主数据源查询测试数据") @GetMapping("/master/{id}") public ResponseResult getTestDataWithMaster(@PathVariable Long id) { return ResponseResult.success(testMasterService.getTestById(id)); // 使用主数据源查询数据 } @Operation(summary = "使用从数据源查询测试数据", description = "使用从数据源查询测试数据") @GetMapping("/slave/{id}") public ResponseResult getTestDataWithSlave(@PathVariable Long id) { return ResponseResult.success(testSlaveService.getTestById(id)); // 使用从数据源查询数据 } } ``` ## 4. 使用方法 ### 4.1 注解方式 使用 `@DS` 注解可以指定方法或类使用的数据源: ```java // 类级别:整个类的方法都使用 master 数据源 @Service @DS("master") public class TestServiceImpl { // ... } // 方法级别:该方法使用 slave 数据源(优先级高于类级别) @DS("slave") public TestEntity getTestById(Long id) { return getById(id); } ``` ### 4.2 动态数据源名称 支持从方法参数或上下文中获取动态数据源名称: ```java // 从方法参数中获取数据源名称 @DS("#datasourceName") public TestEntity getTestById(Long id, String datasourceName) { return getById(id); } // 从上下文或SpEL表达式中获取数据源名称 @DS("#{@systemConfig.getDatasourceName()}") public TestEntity getTestById(Long id) { return getById(id); } ``` ### 4.3 数据源优先级 数据源的优先级顺序为: 1. 方法上的 `@DS` 注解 2. 类上的 `@DS` 注解 3. 全局默认数据源(primary) 注意:Service 层的 @DS 注解具有更高优先级 ## 5. 测试验证 ### 5.1 编译测试 运行以下命令编译项目,确保配置正确: ```bash cd d:\workSpace\tacit; mvn clean compile -pl tacit-admin -am ``` ### 5.2 运行测试 启动项目后,通过以下方式测试多数据源: 1. **使用主数据源创建数据**: ```bash POST /multi-datasource/master/create Content-Type: application/json { "name": "测试用户", "age": 25, "email": "test@example.com" } ``` 2. **使用主数据源查询数据**: ```bash GET /multi-datasource/master/1 ``` 3. **使用从数据源查询数据**: ```bash GET /multi-datasource/slave/1 ``` ## 6. 注意事项 1. **依赖冲突**:确保项目中没有其他数据源相关的依赖冲突,如 `spring-boot-starter-jdbc` 或其他动态数据源框架。 2. **数据源名称**:数据源名称必须与配置文件中的名称一致,大小写敏感。 3. **事务管理**:多数据源环境下,事务管理需要特别注意,建议使用 `@DSTransactional` 注解替代 `@Transactional` 注解。 4. **严格模式**:生产环境建议开启严格模式(`strict: true`),确保数据源名称正确。 5. **性能考虑**:频繁切换数据源会带来性能开销,建议根据业务场景合理设计数据源使用策略。 6. **配置中心**:如果使用配置中心(如 Nacos),可以将数据源配置迁移到配置中心,便于动态调整。 ## 7. 常见问题 ### 7.1 数据源切换不生效 - 检查 `@DS` 注解是否正确添加到方法或类上 - 检查数据源名称是否与配置文件一致 - 检查是否开启了严格模式,以及默认数据源是否配置正确 ### 7.2 事务不生效 - 使用 `@DSTransactional` 注解替代 `@Transactional` 注解 - 确保事务方法是 `public` 修饰的 - 确保事务方法不是通过内部调用的(Spring AOP 代理机制)