一、自定义生成SqlSessionFactory
写一个类,在类的定义上加两个注解:
@Configuration
@EnableConfigurationProperties(MybatisPlusProperties.class)
类中添加以下方法,生成自定义SqlSessionFactory:
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
// 方法中,调用自定义的FactoryBean
MybatisSqlSessionFactoryBeanRewrite factory = new MybatisSqlSessionFactoryBeanRewrite();
}
二、重写MybatisSqlSessionFactoryBean为MybatisSqlSessionFactoryBeanRewrite
修改以下方法:
protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
// 修改生成SqlSessionFactory的方式,把MybatisSqlSessionFactoryBuilder修改为MybatisSqlSessionFactoryBuilderRewrite,其余不变。
final SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilderRewrite().build(targetConfiguration);
}
三、重写MybatisSqlSessionFactoryBuilder为MybatisSqlSessionFactoryBuilderRewrite;重写SqlSessionFactoryBuilder为SqlSessionFactoryBuilderRewrite,修改SqlSessionFactoryBuilderRewrite的build方法:
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactoryRewrite(config);
}
四、重写DefaultSqlSessionFactory为DefaultSqlSessionFactoryRewrite
修改openSessionFromDataSource方法:
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
log.info("切换数据源");
Long userId = ThreadLocalUtil.get();
SysTenant sysTenant = null;
try (
Connection connection = environment.getDataSource().getConnection()
) {
connection.setAutoCommit(true);
Statement state = connection.createStatement();
ResultSet resultSet = state.executeQuery("select * from sys_tenant where sys_tenant_id = " + userId);
List<SysTenant> list = new ArrayList<SysTenant>();
while(resultSet.next())
{
Integer id = resultSet.getInt(1);
String tenantId = resultSet.getString(2);
String type = resultSet.getString(3);
String driverClassName = resultSet.getString(4);
String jdbcUrl = resultSet.getString(5);
String username = resultSet.getString(6);
String password = resultSet.getString(7);
String dataBase = resultSet.getString(8);
SysTenant sysTenantDatabase = new SysTenant();
sysTenantDatabase.setId(id);
sysTenantDatabase.setTenantId(tenantId);
sysTenantDatabase.setType(type);
sysTenantDatabase.setDriverClassName(driverClassName);
sysTenantDatabase.setJdbcUrl(jdbcUrl);
sysTenantDatabase.setUsername(username);
sysTenantDatabase.setPassword(password);
sysTenantDatabase.setDataBase(dataBase);
list.add(sysTenantDatabase);
}
if (list.size() <= NumberConstants.INT_ZERO) {
throw new RuntimeException("租户信息异常,请配置租户");
}
sysTenant = list.get(NumberConstants.INT_ZERO);
} catch (SQLException e) {
log.error("查询数据源失败", e);
}
DataSourceBuilder<?> dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.driverClassName(sysTenant.getDriverClassName());
dataSourceBuilder.url(sysTenant.getJdbcUrl());
dataSourceBuilder.username(sysTenant.getUsername());
dataSourceBuilder.password(sysTenant.getPassword());
DataSource source = dataSourceBuilder.build();
tx = transactionFactory.newTransaction(source, level, autoCommit);
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(tx);
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
五、以上方法可以根据ThreadLocal中的值切换数据源,如果需要根据传入的参数切换数据源,修改DefaultSqlSession类中的方法,从入参parameter中,可取出参数值。