直接上代码:
spring-jdbc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd"
default-lazy-init="true">
<!-- base dataSource -->
<bean name="baseDataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<property name="initialSize" value="5" />
<property name="maxActive" value="100" />
<property name="minIdle" value="10" />
<property name="maxWait" value="600000" />
<property name="validationQuery" value="SELECT 'x'" />
<property name="testOnBorrow" value="true" />
<property name="testOnReturn" value="true" />
<property name="testWhileIdle" value="true" />
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="removeAbandoned" value="true" />
<property name="removeAbandonedTimeout" value="1800" />
<property name="logAbandoned" value="true" />
<property name="filters" value="mergeStat" />
</bean>
<!-- 主库 -->
<bean name="masterDataSource" parent="baseDataSource" init-method="init">
<property name="driverClassName" value="${mysql.db.driver}" />
<property name="url" value="${master.db.url}" />
<property name="username" value="${master.db.username}" />
<property name="password" value="${master.db.password}" />
</bean>
<!-- 从库 -->
<bean name="slaveDataSource0" parent="baseDataSource" init-method="init">
<property name="driverClassName" value="${mysql.db.driver}" />
<property name="url" value="${slave1.db.url}" />
<property name="username" value="${slave1.db.username}" />
<property name="password" value="${slave1.db.password}" />
</bean>
</beans>
spring-applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<import resource="classpath:spring-jdbc.xml"/>
<!--spring的路由来管理数据源-->
<bean id="dynamicDataSource" class="sf.ibu.dc.datasource.DynamicDataSource">
<property name="targetDataSources">
<map>
<entry value-ref="masterDataSource" key="db_master"/>
<entry value-ref="slaveDataSource0" key="db_slave_0"/>
</map>
</property>
</bean>
<!--spring-mybatis整合-->
<bean id="dynamicsqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dynamicDataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!--配置事务-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dynamicDataSource"/>
</bean>
<!--开启注解事务-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
DynamicDataSource.java
package sf.ibu.dc.datasource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Autowired
private DBContextHolder dbContextHolder;
@Override
protected Object determineCurrentLookupKey() {
return dbContextHolder.getDBType();
}
}
DBContextHolder.java
package sf.ibu.dc.datasource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import sf.ibu.dc.db.mysql.servers.ServerQuantityAndIndex;
import sf.ibu.dc.handy.BizConf;
@Component
public class DBContextHolder {
/** 主库 */
public final static String DB_TYPE_MASTER = "db_master";
/** 从库1 */
public final static String DB_TYPE_SLAVE = "db_slave_%d";
@Autowired
private BizConf bizConf;
private ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public String getDBType() {
String db = contextHolder.get();
if (db == null) {
db = DB_TYPE_MASTER; // 默认是master库
}
return db;
}
public void switch2Slave() {
int index = ServerQuantityAndIndex.self.getIndex();
int slaveDBQuantity = bizConf.getInt("slaveDBQuantity");
//the app start up. slaveDBQuantity is 0. but next time is really value
slaveDBQuantity=slaveDBQuantity==0?1:slaveDBQuantity;
contextHolder.set(String.format(DB_TYPE_SLAVE, index % slaveDBQuantity));
}
public void switch2Master() {
contextHolder.set(DB_TYPE_MASTER);
}
public void clearDBType() {
contextHolder.remove();
}
}
用法:dbContextHolder.switch2Master(); dbContextHolder.switch2Slave();
package sf.ibu.dc.db.mysql.instruction;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import sf.ibu.dc.datasource.DBContextHolder;
@Component
public class InstructionDAO {
@Autowired
private SqlSessionFactory sqlSessionFactory;
@Autowired
private DBContextHolder dbContextHolder;
public InstructionVO queryInstruction(String ip){
dbContextHolder.switch2Slave();
SqlSession session = sqlSessionFactory.openSession();
try {
InstructionI instructionI = session.getMapper(InstructionI.class);
return InstructionVO.self = instructionI.queryInstruction(ip);
} finally {
session.close();
}
}
public int insertInstruction(InstructionVO instructionT){
dbContextHolder.switch2Master();
SqlSession session = sqlSessionFactory.openSession();
try {
InstructionI instructionI = session.getMapper(InstructionI.class);
return instructionI.insertInstruction(instructionT);
} finally {
session.commit();
session.close();
}
}
}
记得查看AbstractRoutingDataSource 源码:https://blog.youkuaiyun.com/u013034378/article/details/81661706,知晓原理才是关键