feat:修改配置文件方式,增加多数据源测试
This commit is contained in:
parent
dc99a73c02
commit
a85a68e8b0
|
|
@ -0,0 +1,336 @@
|
|||
# MyBatis Plus 多数据源配置与使用文档
|
||||
|
||||
## 1. 环境与依赖
|
||||
|
||||
### 1.1 环境要求
|
||||
- Spring Boot 3.x
|
||||
- MyBatis Plus 3.5.x
|
||||
- Java 21
|
||||
|
||||
### 1.2 依赖添加
|
||||
添加 MyBatis Plus 动态数据源依赖:
|
||||
|
||||
```xml
|
||||
<!-- Dynamic Datasource -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||
<version>3.6.1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
## 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<TestEntity> {
|
||||
// 继承 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<TestEntity> {
|
||||
/**
|
||||
* 根据 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<TestMapper, TestEntity> 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<TestMapper, TestEntity> 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<TestEntity> createTestDataWithMaster(@RequestBody TestEntity testEntity) {
|
||||
testMasterService.save(testEntity); // 使用主数据源保存数据
|
||||
return ResponseResult.success(testEntity);
|
||||
}
|
||||
|
||||
@Operation(summary = "使用主数据源查询测试数据", description = "使用主数据源查询测试数据")
|
||||
@GetMapping("/master/{id}")
|
||||
public ResponseResult<TestEntity> getTestDataWithMaster(@PathVariable Long id) {
|
||||
return ResponseResult.success(testMasterService.getTestById(id)); // 使用主数据源查询数据
|
||||
}
|
||||
|
||||
@Operation(summary = "使用从数据源查询测试数据", description = "使用从数据源查询测试数据")
|
||||
@GetMapping("/slave/{id}")
|
||||
public ResponseResult<TestEntity> 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 代理机制)
|
||||
|
||||
|
||||
7
pom.xml
7
pom.xml
|
|
@ -134,13 +134,6 @@
|
|||
<version>${nacos-client.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Cloud Bootstrap -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||
<version>4.0.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringDoc -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
|
|
|
|||
|
|
@ -42,16 +42,17 @@
|
|||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Dynamic Datasource -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||
<version>3.6.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Database -->
|
||||
<!-- <dependency>
|
||||
<groupId>com.oceanbase</groupId>
|
||||
<artifactId>oceanbase-client</artifactId>
|
||||
<version>2.4.0</version>
|
||||
</dependency> -->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Swagger -->
|
||||
|
|
@ -94,11 +95,6 @@
|
|||
<artifactId>resilience4j-spring-boot3</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Cloud Bootstrap -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
package com.tacit.admin.controller;
|
||||
|
||||
import com.tacit.common.entity.ResponseResult;
|
||||
import com.tacit.admin.entity.TestEntity;
|
||||
import com.tacit.admin.service.MethodLevelDSTestService;
|
||||
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.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.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 方法级 @DS 注解使用样例 - 控制器
|
||||
* 演示不同场景下的方法级数据源切换
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/test")
|
||||
@Tag(name = "方法级 @DS 注解测试接口", description = "用于测试方法级 @DS 注解的接口")
|
||||
public class MethodLevelDSTestController {
|
||||
|
||||
@Autowired
|
||||
private MethodLevelDSTestService methodLevelDSTestService;
|
||||
|
||||
@Operation(summary = "示例1:保存到主数据源", description = "使用 @DS(\"master\") 指定使用主数据源")
|
||||
@PostMapping("/save-to-master")
|
||||
public ResponseResult<Boolean> saveToMaster(@RequestBody TestEntity testEntity) {
|
||||
boolean result = methodLevelDSTestService.saveToMaster(testEntity);
|
||||
return ResponseResult.success(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "示例2:从从数据源查询", description = "使用 @DS(\"slave\") 指定使用从数据源")
|
||||
@GetMapping("/get-from-slave/{id}")
|
||||
public ResponseResult<TestEntity> getFromSlave(@PathVariable Long id) {
|
||||
TestEntity result = methodLevelDSTestService.getFromSlave(id);
|
||||
return ResponseResult.success(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "示例3:动态数据源名称", description = "使用 @DS(\"#datasourceName\") 从方法参数中获取数据源名称")
|
||||
@PostMapping("/save-to-dynamic")
|
||||
public ResponseResult<Boolean> saveToDynamicDatasource(@RequestBody TestEntity testEntity,
|
||||
@RequestParam String datasourceName) {
|
||||
boolean result = methodLevelDSTestService.saveToDynamicDatasource(testEntity, datasourceName);
|
||||
return ResponseResult.success(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "示例4:结合事务使用", description = "使用 @DSTransactional 注解支持多数据源事务")
|
||||
@PostMapping("/save-with-transaction")
|
||||
public ResponseResult<Boolean> saveWithTransaction(@RequestBody TestEntity testEntity) {
|
||||
boolean result = methodLevelDSTestService.saveWithTransaction(testEntity);
|
||||
return ResponseResult.success(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "示例5-1:从主数据源查询", description = "同一个类中不同方法使用不同数据源 - 从主数据源查询")
|
||||
@GetMapping("/get-from-master/{id}")
|
||||
public ResponseResult<TestEntity> getFromMaster(@PathVariable Long id) {
|
||||
TestEntity result = methodLevelDSTestService.getFromMaster(id);
|
||||
return ResponseResult.success(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "示例5-2:从从数据源查询", description = "同一个类中不同方法使用不同数据源 - 从从数据源查询")
|
||||
@GetMapping("/get-from-slave-db/{id}")
|
||||
public ResponseResult<TestEntity> getFromSlaveDB(@PathVariable Long id) {
|
||||
TestEntity result = methodLevelDSTestService.getFromSlaveDB(id);
|
||||
return ResponseResult.success(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "示例6:使用默认数据源", description = "不使用 @DS 注解,使用全局默认数据源(primary)")
|
||||
@GetMapping("/get-from-default/{id}")
|
||||
public ResponseResult<TestEntity> getFromDefault(@PathVariable Long id) {
|
||||
TestEntity result = methodLevelDSTestService.getFromDefault(id);
|
||||
return ResponseResult.success(result);
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "示例7:获取mapper方法级数据源切换", description = "传入数据源")
|
||||
@GetMapping("/get-one/{datasourceName}")
|
||||
public ResponseResult<TestEntity> getFromDefault(@PathVariable String datasourceName) {
|
||||
TestEntity result = methodLevelDSTestService.getOneTest(datasourceName);
|
||||
return ResponseResult.success(result);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
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("/test")
|
||||
@Tag(name = "多数据源测试接口", description = "用于测试多数据源的接口")
|
||||
public class MultiDatasourceTestController {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("testMasterService")
|
||||
private TestService testMasterService;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("testSlaveService")
|
||||
private TestService testSlaveService;
|
||||
|
||||
@Operation(summary = "使用主数据源创建测试数据", description = "使用主数据源创建测试数据")
|
||||
@PostMapping("/master/create")
|
||||
public ResponseResult<TestEntity> createTestDataWithMaster(@RequestBody TestEntity testEntity) {
|
||||
testMasterService.save(testEntity);
|
||||
return ResponseResult.success(testEntity);
|
||||
}
|
||||
|
||||
@Operation(summary = "使用主数据源查询测试数据", description = "使用主数据源查询测试数据")
|
||||
@GetMapping("/master/{id}")
|
||||
public ResponseResult<TestEntity> getTestDataWithMaster(@PathVariable Long id) {
|
||||
return ResponseResult.success(testMasterService.getTestById(id));
|
||||
}
|
||||
|
||||
@Operation(summary = "使用从数据源查询测试数据", description = "使用从数据源查询测试数据")
|
||||
@GetMapping("/slave/{id}")
|
||||
public ResponseResult<TestEntity> getTestDataWithSlave(@PathVariable Long id) {
|
||||
return ResponseResult.success(testSlaveService.getTestById(id));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package com.tacit.admin.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.tacit.common.entity.Base;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
@Data
|
||||
@TableName("test")
|
||||
public class TestEntity{
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
private String name;
|
||||
private Integer age;
|
||||
private String email;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tacit.admin.mapper;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.tacit.admin.entity.TestEntity;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface TestMapper extends BaseMapper<TestEntity> {
|
||||
|
||||
@DS("master")
|
||||
TestEntity getOneTestMaster();
|
||||
|
||||
@DS("slave")
|
||||
TestEntity getOneTestSlave();
|
||||
|
||||
TestEntity getOneTest();
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package com.tacit.admin.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.tacit.admin.entity.TestEntity;
|
||||
|
||||
/**
|
||||
* 方法级 @DS 注解使用样例 - Service 接口
|
||||
* 定义方法级数据源切换的服务方法
|
||||
*/
|
||||
public interface MethodLevelDSTestService extends IService<TestEntity> {
|
||||
|
||||
/**
|
||||
* 示例1:基本的方法级数据源切换 - 保存到主数据源
|
||||
* @param testEntity 测试实体
|
||||
* @return 保存结果
|
||||
*/
|
||||
boolean saveToMaster(TestEntity testEntity);
|
||||
|
||||
/**
|
||||
* 示例2:基本的方法级数据源切换 - 从从数据源查询
|
||||
* @param id 主键ID
|
||||
* @return 查询结果
|
||||
*/
|
||||
TestEntity getFromSlave(Long id);
|
||||
|
||||
/**
|
||||
* 示例3:动态数据源名称 - 从方法参数中获取数据源名称
|
||||
* @param testEntity 测试实体
|
||||
* @param datasourceName 数据源名称
|
||||
* @return 保存结果
|
||||
*/
|
||||
boolean saveToDynamicDatasource(TestEntity testEntity, String datasourceName);
|
||||
|
||||
/**
|
||||
* 示例4:结合事务使用 - 支持多数据源事务
|
||||
* @param testEntity 测试实体
|
||||
* @return 保存结果
|
||||
*/
|
||||
boolean saveWithTransaction(TestEntity testEntity);
|
||||
|
||||
/**
|
||||
* 示例5:同一个类中不同方法使用不同数据源 - 从主数据源查询
|
||||
* @param id 主键ID
|
||||
* @return 查询结果
|
||||
*/
|
||||
TestEntity getFromMaster(Long id);
|
||||
|
||||
/**
|
||||
* 示例5:同一个类中不同方法使用不同数据源 - 从从数据源查询
|
||||
* @param id 主键ID
|
||||
* @return 查询结果
|
||||
*/
|
||||
TestEntity getFromSlaveDB(Long id);
|
||||
|
||||
/**
|
||||
* 示例6:默认数据源 - 使用全局默认数据源
|
||||
* @param id 主键ID
|
||||
* @return 查询结果
|
||||
*/
|
||||
TestEntity getFromDefault(Long id);
|
||||
|
||||
/**
|
||||
* 示例7:获取mapper方法级数据源切换
|
||||
* @param datasourceName 数据源名称
|
||||
* @return 测试结果
|
||||
*/
|
||||
TestEntity getOneTest(String datasourceName);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tacit.admin.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.tacit.admin.entity.TestEntity;
|
||||
|
||||
public interface TestService extends IService<TestEntity> {
|
||||
TestEntity getTestById(Long id);
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
package com.tacit.admin.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
|
||||
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.MethodLevelDSTestService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 方法级 @DS 注解使用样例
|
||||
* 展示不同场景下的方法级数据源切换
|
||||
*/
|
||||
@Service
|
||||
public class MethodLevelDSTestServiceImpl extends ServiceImpl<TestMapper, TestEntity> implements MethodLevelDSTestService {
|
||||
|
||||
/**
|
||||
* 示例1:基本的方法级数据源切换
|
||||
* 使用 @DS("master") 指定使用主数据源
|
||||
* @param testEntity 测试实体
|
||||
* @return 保存结果
|
||||
*/
|
||||
@DS("master")
|
||||
@Override
|
||||
public boolean saveToMaster(TestEntity testEntity) {
|
||||
return save(testEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 示例2:基本的方法级数据源切换
|
||||
* 使用 @DS("slave") 指定使用从数据源
|
||||
* @param id 主键ID
|
||||
* @return 查询结果
|
||||
*/
|
||||
@DS("slave")
|
||||
@Override
|
||||
public TestEntity getFromSlave(Long id) {
|
||||
return getById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 示例3:动态数据源名称
|
||||
* 使用 @DS("#datasourceName") 从方法参数中获取数据源名称
|
||||
* @param testEntity 测试实体
|
||||
* @param datasourceName 数据源名称
|
||||
* @return 保存结果
|
||||
*/
|
||||
@DS("#datasourceName")
|
||||
@Override
|
||||
public boolean saveToDynamicDatasource(TestEntity testEntity, String datasourceName) {
|
||||
return save(testEntity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 示例4:结合事务使用
|
||||
* 使用 @DSTransactional 注解支持多数据源事务
|
||||
* @param testEntity 测试实体
|
||||
* @return 保存结果
|
||||
*/
|
||||
@DS("master")
|
||||
@DSTransactional
|
||||
@Override
|
||||
public boolean saveWithTransaction(TestEntity testEntity) {
|
||||
// 保存数据
|
||||
boolean result = save(testEntity);
|
||||
// 模拟业务逻辑
|
||||
if (result) {
|
||||
// 可以在同一个事务中操作其他数据
|
||||
TestEntity anotherEntity = new TestEntity();
|
||||
anotherEntity.setName("关联数据");
|
||||
anotherEntity.setAge(30);
|
||||
anotherEntity.setEmail("related@example.com");
|
||||
return save(anotherEntity);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 示例5:同一个类中不同方法使用不同数据源
|
||||
* 方法1:使用主数据源
|
||||
* @param id 主键ID
|
||||
* @return 查询结果
|
||||
*/
|
||||
@DS("master")
|
||||
@Override
|
||||
public TestEntity getFromMaster(Long id) {
|
||||
return getById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 示例5:同一个类中不同方法使用不同数据源
|
||||
* 方法2:使用从数据源
|
||||
* @param id 主键ID
|
||||
* @return 查询结果
|
||||
*/
|
||||
@DS("slave")
|
||||
@Override
|
||||
public TestEntity getFromSlaveDB(Long id) {
|
||||
return getById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 示例6:默认数据源
|
||||
* 不使用 @DS 注解,使用全局默认数据源(primary)
|
||||
* @param id 主键ID
|
||||
* @return 查询结果
|
||||
*/
|
||||
@Override
|
||||
public TestEntity getFromDefault(Long id) {
|
||||
return getById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestEntity getOneTest(String datasourceName) {
|
||||
return switch (datasourceName) {
|
||||
case "master" -> baseMapper.getOneTestMaster();
|
||||
case "slave" -> baseMapper.getOneTestSlave();
|
||||
default -> baseMapper.getOneTest();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
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")
|
||||
@DS("master") // 指定使用主数据源
|
||||
public class TestMasterServiceImpl extends ServiceImpl<TestMapper, TestEntity> implements TestService {
|
||||
@Override
|
||||
public TestEntity getTestById(Long id) {
|
||||
return getById(id);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
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")
|
||||
@DS("slave") // 指定使用从数据源
|
||||
public class TestSlaveServiceImpl extends ServiceImpl<TestMapper, TestEntity> implements TestService {
|
||||
@Override
|
||||
public TestEntity getTestById(Long id) {
|
||||
return getById(id);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,16 @@
|
|||
server:
|
||||
port: 8082
|
||||
|
||||
spring:
|
||||
config:
|
||||
import: "optional:nacos:${spring.application.name}.yaml"
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: 117.72.94.232:9091
|
||||
username: nacos
|
||||
password: nacos
|
||||
namespace: dev
|
||||
config:
|
||||
server-addr: 117.72.94.232:9091
|
||||
file-extension: yaml
|
||||
username: nacos
|
||||
password: nacos
|
||||
namespace: dev
|
||||
|
|
@ -1,3 +1,16 @@
|
|||
server:
|
||||
port: 8082
|
||||
|
||||
spring:
|
||||
config:
|
||||
import: "optional:nacos:${spring.application.name}.yaml"
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: 117.72.94.232:9091
|
||||
username: nacos
|
||||
password: nacos
|
||||
namespace: ${nacos.namespace}
|
||||
config:
|
||||
server-addr: 117.72.94.232:9091
|
||||
file-extension: yaml
|
||||
username: nacos
|
||||
password: nacos
|
||||
namespace: ${nacos.namespace}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
spring:
|
||||
application:
|
||||
name: tacit-admin
|
||||
profiles:
|
||||
active: dev
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
spring:
|
||||
application:
|
||||
name: tacit-admin
|
||||
config:
|
||||
import: "optional:nacos:${spring.application.name}.yaml"
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: ${nacos.server-addr:117.72.94.232:9091}
|
||||
username: ${nacos.username:nacos}
|
||||
password: ${nacos.password:nacos}
|
||||
namespace: ${nacos.namespace:33140c53-3f57-4bd2-b9c8-f507581b6ca2}
|
||||
config:
|
||||
server-addr: ${nacos.server-addr:117.72.94.232:9091}
|
||||
file-extension: yaml
|
||||
username: ${nacos.username:nacos}
|
||||
password: ${nacos.password:nacos}
|
||||
namespace: ${nacos.namespace:33140c53-3f57-4bd2-b9c8-f507581b6ca2}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.tacit.admin.mapper.TestMapper">
|
||||
|
||||
<!-- 查询主库数据示例 -->
|
||||
<select id="getOneTestMaster" resultType="com.tacit.admin.entity.TestEntity">
|
||||
SELECT * FROM test LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 查询从库数据示例 -->
|
||||
<select id="getOneTestSlave" resultType="com.tacit.admin.entity.TestEntity">
|
||||
SELECT * FROM test LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 查询从库数据示例 -->
|
||||
<select id="getOneTest" resultType="com.tacit.admin.entity.TestEntity">
|
||||
SELECT * FROM test LIMIT 1
|
||||
</select>
|
||||
</mapper>
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
server:
|
||||
port: 8082
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
driver-class-name: com.oceanbase.jdbc.Driver
|
||||
url: jdbc:oceanbase://localhost:2881/tacit?useUnicode=true&characterEncoding=utf-8&useSSL=false
|
||||
username: root
|
||||
password: password
|
||||
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
mapper-locations: classpath*:mapper/**/*.xml
|
||||
type-aliases-package: com.tacit.admin.entity
|
||||
|
||||
# Swagger Configuration
|
||||
springdoc:
|
||||
api-docs:
|
||||
enabled: true
|
||||
path: /v3/api-docs
|
||||
swagger-ui:
|
||||
enabled: true
|
||||
path: /swagger-ui.html
|
||||
|
||||
# Logging Configuration
|
||||
logging:
|
||||
level:
|
||||
com.tacit.admin: debug
|
||||
|
|
@ -86,11 +86,6 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Cloud Bootstrap -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.tacit</groupId>
|
||||
<artifactId>common-redis</artifactId>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,17 @@
|
|||
server:
|
||||
port: 8083
|
||||
spring:
|
||||
config:
|
||||
import: "optional:nacos:${spring.application.name}.yaml"
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: 117.72.94.232:9091
|
||||
username: nacos
|
||||
password: nacos
|
||||
namespace: dev
|
||||
config:
|
||||
server-addr: 117.72.94.232:9091
|
||||
file-extension: yaml
|
||||
username: nacos
|
||||
password: nacos
|
||||
namespace: dev
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,17 @@
|
|||
server:
|
||||
port: 8083
|
||||
spring:
|
||||
config:
|
||||
import: "optional:nacos:${spring.application.name}.yaml"
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: 117.72.94.232:9091
|
||||
username: nacos
|
||||
password: nacos
|
||||
namespace: ${nacos.namespace}
|
||||
config:
|
||||
server-addr: 117.72.94.232:9091
|
||||
file-extension: yaml
|
||||
username: nacos
|
||||
password: nacos
|
||||
namespace: ${nacos.namespace}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
spring:
|
||||
application:
|
||||
name: tacit-app-api
|
||||
profiles:
|
||||
active: dev
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
spring:
|
||||
application:
|
||||
name: tacit-app-api
|
||||
config:
|
||||
import: "optional:nacos:${spring.application.name}.yaml"
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: ${nacos.server-addr:117.72.94.232:9091}
|
||||
username: ${nacos.username:nacos}
|
||||
password: ${nacos.password:nacos}
|
||||
namespace: ${nacos.namespace:33140c53-3f57-4bd2-b9c8-f507581b6ca2}
|
||||
config:
|
||||
server-addr: ${nacos.server-addr:117.72.94.232:9091}
|
||||
file-extension: yaml
|
||||
username: ${nacos.username:nacos}
|
||||
password: ${nacos.password:nacos}
|
||||
namespace: ${nacos.namespace:33140c53-3f57-4bd2-b9c8-f507581b6ca2}
|
||||
|
|
@ -51,12 +51,6 @@
|
|||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Cloud Bootstrap for loading bootstrap.yml in Spring Boot 3.x -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-bootstrap</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Cloud Alibaba Nacos Config -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
|
|
|
|||
|
|
@ -1,2 +1,16 @@
|
|||
server:
|
||||
port: 8081
|
||||
spring:
|
||||
config:
|
||||
import: "optional:nacos:${spring.application.name}.yaml"
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: 117.72.94.232:9091
|
||||
username: nacos
|
||||
password: nacos
|
||||
namespace: dev
|
||||
config:
|
||||
server-addr: 117.72.94.232:9091
|
||||
file-extension: yaml
|
||||
username: nacos
|
||||
password: nacos
|
||||
namespace: dev
|
||||
|
|
@ -1,2 +1,16 @@
|
|||
server:
|
||||
port: 8081
|
||||
spring:
|
||||
config:
|
||||
import: "optional:nacos:${spring.application.name}.yaml"
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: 117.72.94.232:9091
|
||||
username: nacos
|
||||
password: nacos
|
||||
namespace: ${nacos.namespace}
|
||||
config:
|
||||
server-addr: 117.72.94.232:9091
|
||||
file-extension: yaml
|
||||
username: nacos
|
||||
password: nacos
|
||||
namespace: ${nacos.namespace}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
spring:
|
||||
application:
|
||||
name: tacit-gateway
|
||||
main:
|
||||
web-application-type: reactive
|
||||
profiles:
|
||||
active: dev
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
spring:
|
||||
application:
|
||||
name: tacit-gateway
|
||||
config:
|
||||
import: "optional:nacos:${spring.application.name}.yaml"
|
||||
main:
|
||||
web-application-type: reactive
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
server-addr: ${nacos.server-addr:117.72.94.232:9091}
|
||||
username: ${nacos.username:nacos}
|
||||
password: ${nacos.password:nacos}
|
||||
namespace: ${nacos.namespace:33140c53-3f57-4bd2-b9c8-f507581b6ca2}
|
||||
config:
|
||||
server-addr: ${nacos.server-addr:117.72.94.232:9091}
|
||||
file-extension: yaml
|
||||
username: ${nacos.username:nacos}
|
||||
password: ${nacos.password:nacos}
|
||||
namespace: ${nacos.namespace:33140c53-3f57-4bd2-b9c8-f507581b6ca2}
|
||||
|
||||
Loading…
Reference in New Issue