在SqlSessionTemplate上层进行了封装,根据调用的方法,切换master/slave,但是无法支持事务
package com.xjy.study.spring.mybatis;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import javax.sql.DataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.mybatis.spring.SqlSessionTemplate;
public class RWSqlSessionTemplate {
private SqlSessionTemplate sqlSessionTemplate;
private DataSource masterDataSource;
private List<DataSource> slaveDataSources;
private volatile boolean isMaster = true;
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
public void setMasterDataSource(DataSource masterDataSource) {
this.masterDataSource = masterDataSource;
}
public void setSlaveDataSources(List<DataSource> slaveDataSources) {
this.slaveDataSources = slaveDataSources;
}
public <T> T selectOne(String statement, Object parameter) {
switchToSlave();
return sqlSessionTemplate.selectOne(statement, parameter);
}
public int update(String statement, Object parameter) {
switchToMaster();
return this.sqlSessionTemplate.update(statement, parameter);
}
private void switchToSlave() {
if(isMaster) {
switchToSlaveDataSource();
isMaster = false;
}
}
private void switchToMaster() {
if(!isMaster) {
switchToMasterDataSource();
isMaster = true;
}
}
private void switchToSlaveDataSource() {
Configuration configuration = this.sqlSessionTemplate.getSqlSessionFactory().getConfiguration();
Environment oldEnvironment = this.sqlSessionTemplate.getSqlSessionFactory().getConfiguration().getEnvironment();
int index = ThreadLocalRandom.current().nextInt(slaveDataSources.size());
Environment newEnvironment = new Environment(oldEnvironment.getId(), oldEnvironment.getTransactionFactory(), slaveDataSources.get(index));
configuration.setEnvironment(newEnvironment);
}
private void switchToMasterDataSource() {
Configuration configuration = this.sqlSessionTemplate.getSqlSessionFactory().getConfiguration();
Environment oldEnvironment = this.sqlSessionTemplate.getSqlSessionFactory().getConfiguration().getEnvironment();
Environment newEnvironment = new Environment(oldEnvironment.getId(), oldEnvironment.getTransactionFactory(), this.masterDataSource);
configuration.setEnvironment(newEnvironment);
}
}