java中mybatis多数据源读写分离核心是通过abstractroutingdatasource动态路由,主库处理写、从库处理读;需手动配置主从datasource bean,用threadlocal+@ds注解+aop实现运行时切换,推荐使用dynamic-datasource-starter简化开发。

Java 中在 MyBatis(或 MyBatis-Plus)里配置多数据源实现读写分离,核心是让写操作走主库、读操作走从库,并通过 Spring 的 AbstractRoutingDataSource 动态切换数据源。不依赖中间件(如 MyCat),纯客户端路由更轻量、可控性更强。
明确主从数据源配置方式
Spring Boot 启动时需手动定义多个 DataSource Bean,不能依赖自动配置的单数据源:
- 用
@ConfigurationProperties(prefix = "spring.datasource.master")绑定主库配置,创建masterDataSource()Bean - 同理绑定从库配置,创建
slaveDataSource()Bean(可配多个,如slave1、slave2) - 确保
application.yml或properties中分开写明 URL、用户名、密码等,避免前缀冲突
构建动态路由数据源
继承 AbstractRoutingDataSource,重写 determineCurrentLookupKey() 方法,决定当前使用哪个数据源:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
- 通常配合
ThreadLocal存储当前线程的数据源标识(如"master"或"slave") - 在 service 方法入口或 AOP 切面中设置该标识,例如:写操作前调用
DataSourceContextHolder.set("master") - 路由类返回 key 后,Spring 自动从已注册的数据源 Map 中匹配对应 Bean
结合注解控制数据源选择
为提升可读性和复用性,推荐自定义 @DS 注解(如 MyBatis-Plus 的 @DS("slave")):
- 定义注解支持方法级和类级,
@Retention(RetentionPolicy.RUNTIME) - 用 AOP 拦截带该注解的方法,在执行前设置
ThreadLocal值 - 事务方法若标注
@Transactional,默认走主库;若强制走从库,需注意 Spring 事务与数据源切换的兼容性(建议读操作不加事务或使用propagation = Propagation.NOT_SUPPORTED)
适配 MyBatis-Plus 的简化方案
若项目已用 MyBatis-Plus,强烈推荐直接集成 dynamic-datasource-spring-boot-starter:
- Maven 引入
com.baomidou:dynamic-datasource-spring-boot-starter:3.5.0+ -
application.yml中按规范配置spring.datasource.dynamic下的主从数据源 - 直接在 Mapper 接口或 Service 方法上加
@DS("slave")即可切换,无需手写路由类 - 支持负载均衡策略(如随机、轮询)、健康检查、默认数据源 fallback 等生产级能力
关键点在于:数据源是“配置出来”的,路由是“运行时选出来的”,而读写分离逻辑是“由业务语义驱动的”。只要主从数据库已搭建好复制关系,代码层只需专注路由策略和调用约定。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










