上一篇文件《SpringBoot实现多数据源(一)【普通版切换】》
二、通过 Mybatis 插件切换数据源
通过 Mybatis 结合插件实现读写分离的数据源
- 配置Mybatis数据源插件
- DynamicDataSourcePlugin
package com.vinjcent.plugin;
import com.vinjcent.config.DynamicDataSource;
import com.vinjcent.constants.DataSourceConstants;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Component;
@Component
@Intercepts(
{
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})
}
)
public class DynamicDataSourcePlugin implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 拿到当前方法(update、query)所有参数
Object[] objects = invocation.getArgs();
// MappedStatement 封装CRUD所有的元素和SQL
MappedStatement ms = (MappedStatement) objects[0];
// 读方法
if (ms.getSqlCommandType().equals(SqlCommandType.SELECT)) {
DynamicDataSource.name.set(DataSourceConstants.READ_DATASOURCE);
} else {
// 写方法
DynamicDataSource.name.set(DataSourceConstants.WRITE_DATASOURCE);
}
return invocation.proceed();
}
}
完成上面的配置即可,因为 MybatisAutoConfiguration.class 会在构造时,自动将我们配置的 DynamicDataSourcePlugin 这个实现了 Mybatis 接口 Interceptor 的bean 进行自动注入
- 修改 PeopleController
- 将
DynamicDataSource.name.set(DataSourceConstants.xxx);
删去即可
- 将
package com.vinjcent.config;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfiguration {
@Bean(name = "readDatasource")
@ConfigurationProperties(prefix = "spring.datasource.read")
public DataSource readDatasource() {
// 底层会自动拿到spring.datasource中的配置,创建一个DruidDataSource
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "writeDatasource")
@ConfigurationProperties(prefix = "spring.datasource.write")
public DataSource writeDatasource() {
// 底层会自动拿到spring.datasource中的配置,创建一个DruidDataSource
return DruidDataSourceBuilder.create().build();
}
}
- 测试 controller 中的接口,是否能够正常进行读写分离