Mybatis-Plus多数据源
Mybatis-Plus的多数据源切换是通过AOP实现的,我们常用的com.baomidou.dynamic.datasource.annotation.DS就是切换的依据。但这种做法只适用于Service方法里只有一个数据源的情况,如果Service方法里涉及到了多个数据源,就会出现误读的情况。
误读:Service配置的是DS("db1"), 方法1中要读一个db2里的表A,就会提示db1.tableA not exists
怎么解决呢?我们知道ORM类可以打com.baomidou.mybatisplus.annotation.TableName注解,TableName里有个schema属性。追踪下去,我们看到com.baomidou.mybatisplus.core.metadata.TableInfoHelper#initTableName用到了schema属性,并把表名装饰成schema+"."+tableName的格式。这样就解决了误读的问题啦~
private static String[] initTableName(Class<?> clazz, GlobalConfig globalConfig, TableInfo tableInfo) {
/* 数据库全局配置 */
GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
// 获取ORM类上的TableName注解
TableName table = clazz.getAnnotation(TableName.class);
String tableName = clazz.getSimpleName();
String tablePrefix = dbConfig.getTablePrefix();
String schema = dbConfig.getSchema();
...
if (table != null) {
...
// 如果TableName注解里的schema不为空,则获取
if (StringUtils.isNotBlank(table.schema())) {
schema = table.schema();
}
...
} else {
...
}
...
// 将schema拼接到tableName前
if (StringUtils.isNotBlank(schema)) {
targetTableName = schema + StringPool.DOT + targetTableName;
}
tableInfo.setTableName(targetTableName);
...
}
还有一种需要多数据源但DS不给力的情况,就是在代码层面实现读-写分离。这种场景可以通过实现一个org.apache.ibatis.plugin.Interceptor拦截方法来达到目的。
多数据源事务(JTA)
JTA包括事务管理器(Transaction Manager)和一个或多个支持 XA 协议的资源管理器 ( Resource Manager ) 两部分, 可以将资源管理器看做任意类型的持久化数据存储;事务管理器则承担着所有事务参与单元的协调与控制。
JTA只是提供了一个接口,并没有提供具体的实现。
Atomikos对其进行了实现,而后SpringBoot将其进行了整合,对其进行了托管,很方便开发者拿来即用。
接入步骤:
1. 根据配置,创建AtomikosDataSourceBean,管理一个XA数据源。多数据源会有多个实例。
2. 把AtomikosDataSourceBean交给SqlSessionFactory管理。
3. 配置JTA事务管理。
我们用的是Mybatis-Plus,所以在第一步,我们需要接管Mybatis-Plus的数据源配置,再在第二步将AtomikosDataSourceBean交托给Mybatis-Plus的SqlSessionFactory管理。
下面来看看具体的代码实现:
步骤1:接