MyBatis 多数据源配置
# MyBatis 多数据源配置
# 1. 手动配置多数据源
手动配置是最基础的多数据源实现方式,通过显式定义多个数据源并针对不同的业务场景选择合适的数据源。
# 1.1 配置多个数据源
首先,在 application.yml
中定义多个数据源的配置:
spring:
datasource:
master: # 主数据源配置
url: jdbc:mysql://master-host:3306/db_name?useSSL=false
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
slave: # 从数据源配置
url: jdbc:mysql://slave-host:3306/db_name?useSSL=false
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
2
3
4
5
6
7
8
9
10
11
12
然后,创建数据源配置类:
@Configuration // 标记为 Spring 配置类
public class DataSourceConfig {
@Bean
@Primary // 标记为主要的数据源,默认情况下使用此数据源
@ConfigurationProperties(prefix = "spring.datasource.master") // 绑定 application.yml 中的配置
public DataSource masterDataSource() {
return DataSourceBuilder.create().build(); // 创建主数据源
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.slave") // 绑定从数据源配置
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build(); // 创建从数据源
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1.2 为每个数据源配置 MyBatis
为了让 MyBatis 能够使用这些数据源,需要为每个数据源配置 SqlSessionFactory
和 SqlSessionTemplate
:
@Configuration // 标记为配置类
@MapperScan(basePackages = "com.example.master.mapper", sqlSessionTemplateRef = "masterSqlSessionTemplate") // 指定主数据源的 Mapper 路径
public class MasterDataSourceConfig {
@Autowired
private DataSource masterDataSource; // 注入主数据源
@Bean
public SqlSessionFactory masterSqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); // 创建 SqlSessionFactoryBean
factoryBean.setDataSource(masterDataSource); // 设置数据源
// 配置 Mapper XML 文件位置
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath:mapper/master/*.xml")); // 指定 XML 文件路径
return factoryBean.getObject(); // 返回 SqlSessionFactory 实例
}
@Bean
public SqlSessionTemplate masterSqlSessionTemplate() throws Exception {
return new SqlSessionTemplate(masterSqlSessionFactory()); // 创建 SqlSessionTemplate
}
@Bean
public PlatformTransactionManager masterTransactionManager() {
return new DataSourceTransactionManager(masterDataSource); // 创建事务管理器
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
同样地,为从数据源创建配置类:
@Configuration // 标记为配置类
@MapperScan(basePackages = "com.example.slave.mapper", sqlSessionTemplateRef = "slaveSqlSessionTemplate") // 指定从数据源的 Mapper 路径
public class SlaveDataSourceConfig {
@Autowired
private DataSource slaveDataSource; // 注入从数据源
@Bean
public SqlSessionFactory slaveSqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); // 创建 SqlSessionFactoryBean
factoryBean.setDataSource(slaveDataSource); // 设置数据源
// 配置 Mapper XML 文件位置
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath:mapper/slave/*.xml")); // 指定 XML 文件路径
return factoryBean.getObject(); // 返回 SqlSessionFactory 实例
}
@Bean
public SqlSessionTemplate slaveSqlSessionTemplate() throws Exception {
return new SqlSessionTemplate(slaveSqlSessionFactory()); // 创建 SqlSessionTemplate
}
@Bean
public PlatformTransactionManager slaveTransactionManager() {
return new DataSourceTransactionManager(slaveDataSource); // 创建事务管理器
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 1.3 使用手动配置的多数据源
使用手动配置的多数据源时,需要通过不同的 Mapper 接口访问不同的数据源:
@Service // 标记为服务类
public class UserService {
@Autowired
private MasterUserMapper masterUserMapper; // 注入主数据源的 Mapper
@Autowired
private SlaveUserMapper slaveUserMapper; // 注入从数据源的 Mapper
public void createUser(User user) {
masterUserMapper.insert(user); // 写操作使用主数据源
}
public List<User> getAllUsers() {
return slaveUserMapper.findAll(); // 读操作使用从数据源
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 2. 动态数据源实现读写分离
手动配置多数据源的方式需要为每个操作显式指定使用哪个数据源,较为繁琐。动态数据源通过 AOP 实现自动数据源切换,更加灵活。
# 2.1 创建动态数据源的核心组件
首先,创建一个动态数据源持有者,用于保存当前线程使用的数据源:
public class DynamicDataSourceHolder {
public static final String MASTER = "master"; // 主库标识
public static final String SLAVE = "slave"; // 从库标识
// 使用 ThreadLocal 确保线程安全
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>(); // 存储当前线程的数据源类型
// 设置当前线程的数据源
public static void setDataSourceType(String dataSourceType) {
CONTEXT_HOLDER.set(dataSourceType); // 设置数据源类型
}
// 获取当前线程的数据源,默认返回主库
public static String getDataSourceType() {
return CONTEXT_HOLDER.get() == null ? MASTER : CONTEXT_HOLDER.get(); // 获取数据源类型
}
// 清除当前线程的数据源类型
public static void clearDataSourceType() {
CONTEXT_HOLDER.remove(); // 移除当前线程的数据源类型
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
接下来,创建继承自 Spring 的 AbstractRoutingDataSource
的动态数据源类:
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceHolder.getDataSourceType(); // 返回当前线程的数据源类型
}
}
2
3
4
5
6
# 2.2 定义数据源切换注解
创建自定义注解用于标记应该使用哪个数据源:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Master {
// 可以添加属性,例如指定具体的主库
String value() default "";
}
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Slave {
// 可以添加属性,例如指定具体的从库
String value() default "";
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这些注解需要通过 AOP 拦截并处理,如前面动态数据源实现中的 DataSourceAspect
。
# 2.3 配置动态数据源
创建动态数据源配置类:
@Configuration // 标记为配置类
@EnableTransactionManagement // 启用事务管理
public class DynamicDataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.master") // 绑定主数据源配置
public DataSource masterDataSource() {
return DataSourceBuilder.create().build(); // 创建主数据源
}
@Bean
@ConfigurationProperties("spring.datasource.slave") // 绑定从数据源配置
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build(); // 创建从数据源
}
@Bean
@Primary // 设置为主要的数据源 Bean
public DataSource dynamicDataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DynamicDataSourceHolder.MASTER, masterDataSource()); // 添加主数据源
targetDataSources.put(DynamicDataSourceHolder.SLAVE, slaveDataSource()); // 添加从数据源
DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();
dataSource.setTargetDataSources(targetDataSources); // 设置目标数据源集合
dataSource.setDefaultTargetDataSource(masterDataSource()); // 设置默认数据源
return dataSource; // 返回动态数据源
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dynamicDataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dynamicDataSource); // 设置数据源
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath:mapper/**/*.xml")); // 设置 Mapper XML 文件位置
return sqlSessionFactoryBean.getObject(); // 返回 SqlSessionFactory
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 2.4 实现数据源切换的 AOP
创建切面类,根据方法上的注解或命名规则切换数据源:
@Aspect // 标记为切面类
@Component // 注册为 Spring Bean
@Order(1) // 设置切面优先级,确保在事务切面之前执行
public class DataSourceAspect {
private static final Logger log = LoggerFactory.getLogger(DataSourceAspect.class);
// 定义切点:使用 @Master 注解的方法或类
@Pointcut("@annotation(com.example.annotation.Master) || @within(com.example.annotation.Master)")
public void masterPointcut() {}
// 定义切点:使用 @Slave 注解的方法或类
@Pointcut("@annotation(com.example.annotation.Slave) || @within(com.example.annotation.Slave)")
public void slavePointcut() {}
// 在 @Master 注解的方法执行前,切换到主库
@Before("masterPointcut()")
public void beforeMaster() {
log.debug("Switch to MASTER database");
DynamicDataSourceHolder.setDataSourceType(DynamicDataSourceHolder.MASTER); // 设置为主库数据源
}
// 在 @Slave 注解的方法执行前,切换到从库
@Before("slavePointcut()")
public void beforeSlave() {
log.debug("Switch to SLAVE database");
DynamicDataSourceHolder.setDataSourceType(DynamicDataSourceHolder.SLAVE); // 设置为从库
}
// 方法执行后清除数据源标识
@After("masterPointcut() || slavePointcut()")
public void after() {
DynamicDataSourceHolder.clearDataSourceType(); // 清除数据源标识
}
// 对未添加注解的方法,根据方法名判断使用哪个数据源
@Before("execution(* com.example.service.*.*(..)) && !masterPointcut() && !slavePointcut()")
public void beforeDefault(JoinPoint point) {
String methodName = point.getSignature().getName(); // 获取方法名
// 查询方法使用从库,其他方法使用主库
if (methodName.startsWith("select") || methodName.startsWith("get") ||
methodName.startsWith("find") || methodName.startsWith("query") ||
methodName.startsWith("list") || methodName.startsWith("count")) {
log.debug("Switch to SLAVE database - Method name: {}", methodName);
DynamicDataSourceHolder.setDataSourceType(DynamicDataSourceHolder.SLAVE); // 设置为从库
} else {
log.debug("Switch to MASTER database - Method name: {}", methodName);
DynamicDataSourceHolder.setDataSourceType(DynamicDataSourceHolder.MASTER); // 设置为主库
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 2.5 使用动态数据源
在服务类中使用动态数据源:
@Service // 标记为服务类
public class UserService {
@Autowired
private UserMapper userMapper; // 注入统一的 Mapper
@Master // 指定使用主库
public void createUser(User user) {
userMapper.insert(user); // 写操作使用主库
}
@Slave // 指定使用从库
public List<User> getAllUsers() {
return userMapper.findAll(); // 读操作使用从库
}
// 未添加注解,会根据方法名决定使用哪个数据源
public User findById(Long id) {
return userMapper.findById(id); // 方法名以 find 开头,自动路由到从库
}
// 未添加注解,会根据方法名决定使用哪个数据源
public void updateUser(User user) {
userMapper.update(user); // 方法名以 update 开头,自动路由到主库
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 3. 使用第三方库实现多数据源和读写分离
# 3.1 Baomidou Dynamic Datasource
Baomidou Dynamic Datasource 是一个专为 MyBatis 设计的动态数据源切换框架,提供了更简单的配置和使用方式。
引入依赖
根据 Spring Boot 版本选择合适的依赖:
<!-- Spring Boot 2.x -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.2</version> <!-- 使用最新版本 -->
</dependency>
<!-- Spring Boot 3.x (JDK 17+) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
<version>3.5.2</version> <!-- 使用最新版本 -->
</dependency>
2
3
4
5
6
7
8
9
10
11
12
13
配置数据源
在 application.yml
中配置多数据源:
spring:
datasource:
dynamic:
primary: master # 设置默认数据源
strict: false # 是否严格匹配数据源,false 表示找不到数据源时使用默认数据源
datasource:
master: # 主库配置
url: jdbc:mysql://localhost:3306/master_db
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
slave_1: # 从库1配置
url: jdbc:mysql://localhost:3307/slave_db
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
slave_2: # 从库2配置
url: jdbc:mysql://localhost:3308/slave_db
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
使用 @DS 注解切换数据源
Baomidou Dynamic Datasource 提供了 @DS
注解来指定使用哪个数据源:
@Service // 标记为服务类
public class UserService {
@DS("master") // 使用主库数据源
public void createUser(User user) {
userMapper.insert(user); // 写操作使用主库
}
@DS("slave_1") // 指定使用从库1
public List<User> getAllUsers() {
return userMapper.findAll(); // 读操作使用从库1
}
@DS("slave_2") // 指定使用从库2
public User getUserById(Long id) {
return userMapper.findById(id); // 使用从库2查询
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
使用 @Master 和 @Slave 注解
Baomidou Dynamic Datasource 还提供了预定义的 @Master
和 @Slave
注解,这些注解是 @DS
的特定形式:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@DS("master") // 底层使用 @DS("master")
public @interface Master {
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@DS("slave") // 底层使用 @DS("slave")
public @interface Slave {
}
2
3
4
5
6
7
8
9
10
11
12
13
使用这些注解:
@Service // 标记为服务类
public class UserService {
@Master // 使用主库数据源
public void createUser(User user) {
userMapper.insert(user); // 写操作使用主库
}
@Slave // 使用从库数据源,会自动在从库组中负载均衡
public List<User> getAllUsers() {
return userMapper.findAll(); // 读操作使用从库
}
}
2
3
4
5
6
7
8
9
10
11
12
13
配置数据源组和负载均衡
可以将多个从库配置为一个组,并设置负载均衡策略:
spring:
datasource:
dynamic:
primary: master
datasource:
master: # 主库
url: jdbc:mysql://localhost:3306/master_db
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
slave_1: # 从库1
url: jdbc:mysql://localhost:3307/slave_db
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
slave_2: # 从库2
url: jdbc:mysql://localhost:3308/slave_db
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
# 配置从库组
strategy: com.baomidou.dynamic.datasource.strategy.LoadBalanceDynamicDataSourceStrategy # 负载均衡策略
# 设置数据源组
ds-group:
slave: # slave 组包含 slave_1 和 slave_2
- slave_1
- slave_2
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
然后可以使用 @DS("slave")
或 @Slave
注解选择从库组,框架会自动在从库之间进行负载均衡。
# 3.2 使用 ShardingSphere 实现读写分离
Apache ShardingSphere 是一个功能更加全面的数据库中间件,除了读写分离外,还支持分库分表、数据加密等高级功能。
引入依赖
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.3.2</version> <!-- 使用最新版本 -->
</dependency>
2
3
4
5
配置读写分离
在 application.yml
中配置 ShardingSphere 的读写分离:
spring:
shardingsphere:
mode:
type: Standalone # 运行模式:单机模式
repository:
type: JDBC
datasource:
names: master,slave1,slave2 # 数据源名称
# 主库配置
master:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/master_db
username: root
password: password
# 从库1配置
slave1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3307/slave_db
username: root
password: password
# 从库2配置
slave2:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3308/slave_db
username: root
password: password
# 规则配置
rules:
# 读写分离规则
readwrite-splitting:
data-sources:
readwrite_ds: # 读写分离数据源名称
type: Static # 静态读写分离
props:
write-data-source-name: master # 写数据源名称
read-data-source-names: slave1,slave2 # 读库数据源名称列表
load-balancer-name: round_robin # 负载均衡算法名称
# 负载均衡算法配置
load-balancers:
round_robin: # 负载均衡算法名称
type: ROUND_ROBIN # 轮询算法
# 属性配置
props:
sql-show: true # 显示SQL
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
使用 ShardingSphere 实现的读写分离
ShardingSphere 会根据 SQL 类型自动路由,无需添加额外注解:
@Service // 标记为服务类
public class UserService {
@Autowired
private UserMapper userMapper; // 注入 Mapper
// 插入操作自动路由到主库
public void createUser(User user) {
userMapper.insert(user); // 自动路由到主库
}
// 查询操作自动路由到从库
public List<User> getAllUsers() {
return userMapper.findAll(); // 自动路由到从库
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
强制使用主库
有时需要确保查询操作也使用主库(例如,需要强一致性的场景),可以使用 ShardingSphere 的 API:
@Service // 标记为服务类
public class UserService {
public User getLatestUserFromMaster(Long id) {
// 设置强制使用主库
HintManager.getInstance().setWriteRouteOnly();
try {
return userMapper.findById(id); // 强制使用主库查询
} finally {
// 清除路由设置
HintManager.clear();
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
也可以封装为注解:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ForceMaster {
}
@Aspect
@Component
public class ShardingSphereAspect {
@Around("@annotation(ForceMaster)")
public Object aroundForceMaster(ProceedingJoinPoint joinPoint) throws Throwable {
HintManager.getInstance().setWriteRouteOnly(); // 设置强制主库
try {
return joinPoint.proceed(); // 执行方法
} finally {
HintManager.clear(); // 清除设置
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 4. 多数据源注解使用
在多数据源架构中,注解是实现数据源切换的关键。不同框架提供了不同的注解实现。
# 4.1 自定义实现中的注解
在自定义动态数据源实现中,通常会定义如下注解:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Master {
// 可以添加属性,例如指定具体的主库
String value() default "";
}
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Slave {
// 可以添加属性,例如指定具体的从库
String value() default "";
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
这些注解需要通过 AOP 拦截并处理,如前面动态数据源实现中的 DataSourceAspect
。
# 4.2 Baomidou Dynamic Datasource 注解详解
Baomidou Dynamic Datasource 提供了更丰富的注解支持:
@DS 注解:基础注解,用于指定数据源
@DS("master") // 使用主库 public void updateUser(User user) { ... } @DS("slave_1") // 使用特定从库 public List<User> getAllUsers() { ... } @DS("slave") // 使用从库组(负载均衡) public User getById(Long id) { ... }
1
2
3
4
5
6
7
8@Master 注解:指定使用主库的语法糖
@Master // 等同于 @DS("master") public void createOrder(Order order) { ... }
1
2@Slave 注解:指定使用从库的语法糖
@Slave // 等同于 @DS("slave") public List<Product> listProducts() { ... }
1
2自定义数据源注解:可以创建更多语义化的注解
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @DS("sharding") // 关联到分片数据源 public @interface Sharding { } // 使用自定义注解 @Sharding public List<Order> getOrdersBySharding() { ... }
1
2
3
4
5
6
7
8
9
10
# 4.3 ShardingSphere 中的数据源控制
ShardingSphere 主要通过 API 而非注解控制路由:
// 强制使用主库
HintManager.getInstance().setWriteRouteOnly();
try {
return userMapper.findById(id); // 强制使用主库查询
} finally {
HintManager.clear(); // 清除设置
}
2
3
4
5
6
7
但可以封装为自定义注解:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ForceMaster {
}
@Aspect
@Component
public class ShardingSphereAspect {
@Around("@annotation(ForceMaster)")
public Object aroundForceMaster(ProceedingJoinPoint joinPoint) throws Throwable {
HintManager.getInstance().setWriteRouteOnly(); // 设置强制主库
try {
return joinPoint.proceed(); // 执行方法
} finally {
HintManager.clear(); // 清除设置
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 4.4 注解使用的最佳实践
- 明确的命名约定:使用
@Master/@Slave
或@ReadWrite/@ReadOnly
这样语义明确的注解。 - 合理的默认行为:对未标注注解的方法,根据方法名称(如以
get/find/select/query
开头的方法使用从库)自动选择数据源。 - 注解的层次:可以在类级别设置默认数据源,在方法级别覆盖特定行为。
- 事务协同:确保与 Spring 的
@Transactional
注解协同工作,通常数据源切换应该在事务开始前完成。 - 监控与日志:为数据源切换添加日志,方便排查问题。
# 5. 多数据源方案选择
根据项目规模和需求选择合适的多数据源方案:
手动配置多数据源
- 优点:直观、完全控制、适合简单场景
- 缺点:代码冗余、难以维护、不够灵活
- 适用场景:简单项目,数据源较少且业务逻辑简单
自定义动态数据源
- 优点:灵活性高、可定制性强
- 缺点:实现复杂、需要自行维护
- 适用场景:对定制化要求高的中型项目
Baomidou Dynamic Datasource
- 优点:配置简单、注解丰富、功能完善
- 缺点:与 MyBatis 绑定较紧
- 适用场景:大多数 MyBatis 项目,特别是需要读写分离的场景
ShardingSphere
- 优点:功能全面、支持分库分表、性能优越
- 缺点:配置较复杂、学习曲线陡峭
- 适用场景:需要分库分表、读写分离等复杂功能的大型项目
选择建议:
- 对于简单项目:优先考虑 Baomidou Dynamic Datasource
- 对于复杂项目:选择 ShardingSphere
- 需要高度定制化:自行实现动态数据源
- 快速原型验证:手动配置多数据源
最终,应根据项目的具体需求、团队技术栈和长期维护成本综合考虑选择合适的多数据源方案。