动态路由数据源
以 Spring Boot 框架为例,将动态路由数据源整合进 BakiDao 中,无侵入式的使用动态路由数据源,需要准备以下几点:
- 使用 Spring Boot 框架
- 引入
rabbit-sql-spring-boot-starter版本 5.3.10+ - 引入一个动态路由数据源例如:
dynamic-datasource-spring-boot-starter - 重写
BakiDao相关方法 - 添加到 Spring 上下文容器中
基于 Spring Boot ,动态路由数据源路由能力实际上内置支持
AbstractRoutingDataSource,具体的实现扩展有很多,或者自己实现一个满足特定业务的动态数据源也行。
核心接口配置
5.3.9以下
继承 SpringManagedBaki 重写方法 databaseInfo():
public DynamicDatasourceBaki extends SpringManagedBaki{
private final Map<String, DatabaseInfo> DB_INFO = new ConcurrentHashMap<>();
public DynamicDatasourceBaki(DataSource dataSource){
super(dataSource);
}
@Override
public @NotNull DatabaseInfo databaseInfo() {
if(getDataSource() instanceof DynamicDataSource){
String key = DynamicDataSourceContextHolder.peek();
return DB_INFO.computeIfAbsent(key, k -> {
return using(DatabaseInfo::of);
});
}
return super.databaseInfo();
}
}
默认情况下,一个 BakiDao 绑定一个数据源,初始化一次 databaseInfo() ,用于提供当前数据库信息给分页查询自动生成合适的分页 SQL 等一些扩展功能。
在动态数据源的情况下,为了适配不同类型的数据库,所以此方法必须重写,记录下不同数据源的信息,为了 BakiDao 内依赖的插件得以正确运行。
实际上重写此方法的大致思路就是:
- 判断当前是不是动态路由数据源
- 通过动态路由数据源上下文当前对象获取当前线程中的数据库名字
- 缓存名字所代表数据源与其匹配的
DatabaseInfo,避免重复请求
不同的动态路由数据源实现有所不同,以上代码例子仅做参考,根据这个思路来实现即可。
添加到 Spring 容器中:
@Bean
public Baki baki(DataSource dataSource,
XQLFileManager xqlFileManager){
DynamicDatasourceBaki baki = new DynamicDatasourceBaki(dataSource);
baki.setXQLFileManager(xqlFileManager);
return baki;
}
根据需要注入其他扩展实现如图:

5.3.9+
无需重写 BakiDao#databaseInfo ,实现接口 com.github.chengyuxing.sql.plugins.DatabaseInfoProvider 配置为 Bean 即可生效。
@Component
public class DynamicDatabaseInfoProvider implements DatabaseInfoProvider {
private final Map<String, DatabaseInfo> INFO = new ConcurrentHashMap<>();
@Override
public @Nullable DatabaseInfo resolve(@NotNull DataSource dataSource, Supplier<DatabaseInfo> supplier) {
if (dataSource instanceof DynamicDataSource) {
String key = DynamicDataSourceContextHolder.peek();
return INFO.computeIfAbsent(key, k -> supplier.get());
}
return null;
}
}
以上实现同样建议使用缓存,每次调用
Supplier<DatabaseInfo> supplier都会获取一个连接,使用缓存避免不必要的开销。
应用
除核心接口 Baki 外, Rabbit SQL 支持接口映射,在动态数据源的场景中,会更加直观规范化。
在接口上添加注解 @DS("slave_db") 即可切换数据源。
推荐使用插件 Generate Mapper... 来生成接口类,其中有3个区域可手动增加内容不会在重复生成的过程中丢失,注解添加在如下区域内 //CODE-BEGIN/END:annotations:
// Rabbit SQL plugin - Your annotations //CODE-BEGIN:annotations
@DS("slave_db")
// Rabbit SQL plugin - End of your annotations //CODE-END:annotations
@XQLMapper("home")
public interface HomeMapper{
}
在 service 中注入 HomeMapper 即可连接 slave_db 这个数据源进行一系列操作。