Spring 讀寫分離配置

直接上代碼:

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.csdn.net/u013034378/article/details/81661706,知曉原理纔是關鍵

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章