spring 集成mybatis動態設置數據源,實現讀寫分離

因爲業務須要,須要用到讀寫分離,可是如今一些現有的中間件知足不了咱們如今複雜的業務邏輯,只有本身在spring裏面搞,幸虧有官方代碼。 一般 spring集成mybatis的集成方式: 第一種是採用MapScannerConfigurer,它將會查找類路徑下的映射器並自動將它們建立成MapperFactoryBean。這種我用的比較少 第二種 是採用接口org.apache.ibatis.session.SqlSession的實現類org.mybatis.spring.SqlSessionTemplate。在dao層直接注入模板 第三種是採用抽象類org.mybatis.spring.support.SqlSessionDaoSupport提供SqlSession。 關於具體配置就請百度。 下面說的是動態切換數據源,網上說的是兩種, 一種是重寫SqlSessionTemplate,重寫getSqlSessionFactory,getConfiguration和SqlSessionInterceptor方法, 另外一種就是重寫SqlSessionDaoSupport,重寫裏面的getSqlSessionFactory方法。第一種我沒有試過,不過網上不少,第二種通過實踐過了,非話很少說,直接上代碼。 首先在你的配置文件裏面設置多數據源mysql

spring-config-datasource-dbcp.xml
<bean id="parentDataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="maxActive" value="30" />
		<property name="initialSize" value="2" />
		<property name="maxWait" value="30000" />
		<property name="maxIdle" value="30" />
		<property name="minIdle" value="1" />
		<property name="testOnBorrow" value="false"></property>
		<property name="testWhileIdle" value="true"></property>
		<property name="validationQuery" value="select 1"></property>
		<property name="timeBetweenEvictionRunsMillis">
			<value>30000</value>
		</property>
		<property name="numTestsPerEvictionRun">
			<value>10</value>
		</property>
		<property name="minEvictableIdleTimeMillis" value="30000"></property>
	</bean>這裏輸入代碼
	<bean id="writeDataSource" parent="parentDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="xxxxxxx" />
		<property name="username" value="xxx" />
		<property name="password" value="xxx" />
	</bean>

	<bean id="readDataSource" parent="parentDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="xxxx" />
		<property name="username" value="xxx" />
		<property name="password" value="xxxx" />
	</bean>

	<!--mybatis與Spring整合 開始 -->
	<bean id="readSqlSessionFactory" name="readSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="configLocation" value="classpath:mybatis_configuration.xml" />
		<property name="dataSource" ref="readDataSource" />
	</bean>
	
	<bean id="writeSqlSessionFactory" name="writeSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="configLocation" value="classpath:mybatis_configuration.xml" />
		<property name="dataSource" ref="writeDataSource" />
	</bean>

以上是mybatis與spring集成的配置文件。到此xml配置完成。 因爲須要在程序裏面切換數據源,還要考慮到多個線程的請求過來,由於咱們須要寫一個幫助類,用來幫助咱們切換數據源spring

public class DBConvertHelper {
	private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();  
	public static String getDbType() {  
        String db = contextHolder.get();  
        if (db == null) {  
            db = Const.DB_TYPE_RW;// 默認是讀寫庫  
        }  
        return db;  
    }    
    public static void setDbType(String str) {  
        contextHolder.set(str);  
    }  
  
    public static void clearDBType() {  
        contextHolder.remove();  
    }  
}

此處用了threadLocal對象來保存線程的副本,他是一個線程私有的對象。Const是一個常量類,代碼以下sql

public interface Const {
	public static final String DB_TYPE_RW = "write";  
	public static final String DB_TYPE_R = "read";  
}

其次就核心類DynamicSqwriteSqlSessionlSessionDaoSupport,他集成DaoSupport類重寫了getSqlSession()方法,具體代碼以下:apache

public class DynamicSqlSessionDaoSupport extends DaoSupport{

	private SqlSession readSqlSession;
	private SqlSession writeSqlSession;

	public void setReadSqlSessionFactory(SqlSessionFactory readSqlSessionFactory) {
		this.readSqlSession = new SqlSessionTemplate(readSqlSessionFactory);
	}

	public void setWriteSqlSessionFactory(SqlSessionFactory writeSqlSessionFactory) {
		this.writeSqlSession = new SqlSessionTemplate(writeSqlSessionFactory);
	}

	public SqlSession getSqlSession() {
		if(Const.DB_TYPE_RW.equals(DBContextHolder.getDbType())){
			return writeSqlSession;
		} else {
			return readSqlSession;
		}
	}

	@Override
	protected void checkDaoConfig() throws IllegalArgumentException {
		notNull(this.readSqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");		
		notNull(this.writeSqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");		
	}

}

此處的readSqlSession,writeSqlSession分別對應配置文件裏面的sqlSession,寫測試代碼 主要是dao層,數據源默認的是寫數據源,因此在須要讀數據源的時候設置一下,dao層集成你寫的動態的session

public class MyMessageDaoImpl extends DynamicSqlSessionDaoSupport implements MyMessageDao{

	@Override
	public List<MyMessage> getByPage(CommonReq commonReq) {
	//	DBContextHolder.setDbType(Const.DB_TYPE_RW);
		return getSqlSession().selectList("MyMessage.selectByPage", commonReq);
	}

	@Override
	public void addFeedBack(FeedBack feedBack) {
		DBContextHolder.setDbType(Const.DB_TYPE_R);
		getSqlSession().insert("MyMessage.addFeedBack", feedBack);		
	}
	
}

就ok了,親測,沒問題,數據源能夠設置多個,mybatis

相關文章
相關標籤/搜索