詳解MyBatis多數(shù)據(jù)源配置(讀寫分離)
MyBatis多數(shù)據(jù)源配置(讀寫分離)
首先說明,本文的配置使用的最直接的方式,實際用起來可能會很麻煩。
實際應用中可能存在多種結(jié)合的情況,你可以理解本文的含義,不要死板的使用。
多數(shù)據(jù)源的可能情況
1.主從
通常是MySQL一主多從的情況,本文的例子就是主從的情況,但是只有兩個數(shù)據(jù)源,所以采用直接配置不會太麻煩,但是不利于后續(xù)擴展,主要是作為一個例子來說明,實際操作請慎重考慮。
2.分庫
當業(yè)務獨立性強,數(shù)據(jù)量大的時候的,為了提高并發(fā),可能會對表進行分庫,分庫后,每一個數(shù)據(jù)庫都需要配置一個數(shù)據(jù)源。
這種情況可以參考本文,但是需要注意每一個數(shù)據(jù)庫對應的Mapper要在不同的包下方便區(qū)分和配置。
另外分庫的情況下也會存在主從的情況,如果你的數(shù)據(jù)庫從庫過多,就參考上面提供的方法,或者尋找其他方式解決。
Mapper分包
分庫的情況下,不同的數(shù)據(jù)庫的Mapper一定放在不同的包下。
主從的情況下,同一個Mapper會同時存在讀寫的情況,創(chuàng)建兩個并不合適,使用同一個即可。但是這種情況下需要注意,Spring對Mapper自動生成的名字是相同的,而且類型也相同,這是就不能直接注入Mapper接口。需要通過SqlSession來解決。
Spring基礎配置
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.isea533.mybatis.service"/>
<context:property-placeholder location="classpath:config.properties"/>
<aop:aspectj-autoproxy/>
<import resource="spring-datasource-master.xml"/>
<import resource="spring-datasource-slave.xml"/>
</beans>
這個文件,主要是引入了spring-datasource-master.xml和spring-datasource-slave.xml。
spring-datasource-master.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="dataSourceMaster" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="driverClassName" value="${master.jdbc.driverClass}"/>
<property name="url" value="${master.jdbc.url}"/>
<property name="username" value="${master.jdbc.user}"/>
<property name="password" value="${master.jdbc.password}"/>
<property name="filters" value="stat"/>
<property name="maxActive" value="20"/>
<property name="initialSize" value="1"/>
<property name="maxWait" value="60000"/>
<property name="minIdle" value="1"/>
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<property name="minEvictableIdleTimeMillis" value="300000"/>
<property name="validationQuery" value="SELECT 'x'"/>
<property name="testWhileIdle" value="true"/>
<property name="testOnBorrow" value="false"/>
<property name="testOnReturn" value="false"/>
</bean>
<bean id="sqlSessionFactory1"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSourceMaster"/>
<property name="mapperLocations">
<array>
<value>classpath:mapper/*.xml</value>
</array>
</property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.isea533.mybatis.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory1"/>
</bean>
<bean id="sqlSessionMaster" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">
<constructor-arg index="0" ref="sqlSessionFactory1"/>
</bean>
<aop:config>
<aop:pointcut id="appService"
expression="execution(* com.isea533.mybatis.service..*Service*.*(..))"/>
<aop:advisor advice-ref="txAdvice1" pointcut-ref="appService"/>
</aop:config>
<tx:advice id="txAdvice1" transaction-manager="transactionManager1">
<tx:attributes>
<tx:method name="select*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<bean id="transactionManager1"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSourceMaster"/>
</bean>
</beans>
spring-datasource-slave.xml
和master區(qū)別不大,主要是id名字和數(shù)據(jù)源配置有區(qū)別。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="dataSourceSlave" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="driverClassName" value="${slave.jdbc.driverClass}"/>
<property name="url" value="${slave.jdbc.url}"/>
<property name="username" value="${slave.jdbc.user}"/>
<property name="password" value="${slave.jdbc.password}"/>
<property name="filters" value="stat"/>
<property name="maxActive" value="20"/>
<property name="initialSize" value="1"/>
<property name="maxWait" value="60000"/>
<property name="minIdle" value="1"/>
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<property name="minEvictableIdleTimeMillis" value="300000"/>
<property name="validationQuery" value="SELECT 'x'"/>
<property name="testWhileIdle" value="true"/>
<property name="testOnBorrow" value="false"/>
<property name="testOnReturn" value="false"/>
</bean>
<bean id="sqlSessionFactory2"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSourceSlave"/>
<property name="mapperLocations">
<array>
<value>classpath:mapper/*.xml</value>
</array>
</property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.isea533.mybatis.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory2"/>
</bean>
<bean id="sqlSessionSlave" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">
<constructor-arg index="0" ref="sqlSessionFactory2"/>
</bean>
<aop:config>
<aop:pointcut id="appService"
expression="execution(* com.isea533.mybatis.service..*Service*.*(..))"/>
<aop:advisor advice-ref="txAdvice2" pointcut-ref="appService"/>
</aop:config>
<tx:advice id="txAdvice2" transaction-manager="transactionManager2">
<tx:attributes>
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
<bean id="transactionManager2"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSourceSlave"/>
</bean>
</beans>
這里需要注意<tx:method name="*" read-only="true"/>是只讀的。如果不是從庫,可以按主庫進行配置。
在下面代碼中:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.isea533.mybatis.mapper"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory2"/> </bean>
必須通過sqlSessionFactoryBeanName來指定不同的sqlSessionFactory。
config.properties
# 數(shù)據(jù)庫配置 - Master master.jdbc.driverClass = com.mysql.jdbc.Driver master.jdbc.url = jdbc:mysql://192.168.1.11:3306/test master.jdbc.user = root master.jdbc.password = jj # - Slave slave.jdbc.driverClass = com.mysql.jdbc.Driver slave.jdbc.url = jdbc:mysql://192.168.1.22:3306/test slave.jdbc.user = root slave.jdbc.password = jj
使用Mapper
這里是針對主從的情況進行設置的,兩個配置掃描的Mapper是一樣的,所以沒法直接注入,需要通過下面的麻煩方式注入。
@Service
public class DemoService {
private CountryMapper writeMapper;
private CountryMapper readMapper;
@Resource(name = "sqlSessionMaster")
public void setWriteMapper(SqlSession sqlSession) {
this.writeMapper = sqlSession.getMapper(CountryMapper.class);
}
@Resource(name = "sqlSessionSlave")
public void setReadMapper(SqlSession sqlSession) {
this.readMapper = sqlSession.getMapper(CountryMapper.class);
}
public int save(Country country){
return writeMapper.insert(country);
}
public List<Country> selectPage(int pageNum, int pageSize) {
PageHelper.startPage(pageNum, pageSize);
return readMapper.select(null);
}
}
因為sqlSession能通過name區(qū)分開,所以這里從sqlSession獲取Mapper。
另外如果需要考慮在同一個事務中寫讀的時候,需要使用相同的writeMapper,這樣在讀的時候,才能獲取事務中的最新數(shù)據(jù)。
以上是主從的情況。
在分庫的情況時,由于不同Mapper在不同的包下,所以可以直接使用@Resource或者@Autowired注入Mapper,不需要通過sqlSession獲取。
本篇文章,只是一個多數(shù)據(jù)源的參考,實際應用時,請根據(jù)自己的情況進行考慮。
后續(xù),我會利用業(yè)余時間,在本文和上面兩個相關鏈接的基礎上,針對MySql多數(shù)據(jù)源,嘗試開發(fā)可以自動切換數(shù)據(jù)源的插件,因為我對這方面的實際應用不是很熟,所以歡迎大家留言分享自己的解決方案,對這些了解的越多,就越有可能開發(fā)出通用的數(shù)據(jù)源切換插件。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- Spring Boot 集成Mybatis實現(xiàn)主從(多數(shù)據(jù)源)分離方案示例
- 詳解Spring Boot整合Mybatis實現(xiàn) Druid多數(shù)據(jù)源配置
- springboot + mybatis配置多數(shù)據(jù)源示例
- Spring Boot + Mybatis多數(shù)據(jù)源和動態(tài)數(shù)據(jù)源配置方法
- Spring3 整合MyBatis3 配置多數(shù)據(jù)源動態(tài)選擇SqlSessionFactory詳細教程
- 詳解SpringBoot和Mybatis配置多數(shù)據(jù)源
- Spring+MyBatis多數(shù)據(jù)源配置實現(xiàn)示例
- Spring Boot+Mybatis+Druid+PageHelper實現(xiàn)多數(shù)據(jù)源并分頁的方法
- Spring Boot 整合mybatis 使用多數(shù)據(jù)源的實現(xiàn)方法
- Mybatis注解實現(xiàn)多數(shù)據(jù)源讀寫分離詳解
相關文章
SpringBoot中引入MyBatisPlus的常規(guī)操作
這篇文章主要介紹了SpringBoot中引入MyBatisPlus的常規(guī)操作,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-11-11
Maven項目部署到服務器設置訪問路徑以及配置虛擬目錄的方法
今天小編就為大家分享一篇關于Maven項目部署到服務器設置訪問路徑以及配置虛擬目錄的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-02-02
Mybatis實體類屬性與數(shù)據(jù)庫不一致解決方案
這篇文章主要介紹了Mybatis實體類屬性與數(shù)據(jù)庫不一致解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-10-10
淺談JDK8中的Duration Period和ChronoUnit
在JDK8中,引入了三個非常有用的時間相關的API:Duration,Period和ChronoUnit。他們都是用來對時間進行統(tǒng)計的,本文將會詳細講解一下這三個API的使用2021-06-06
IDEA啟動服務提示端口被占用,Web?server?failed?to?start.Port?was?al
這篇文章主要介紹了IDEA啟動服務提示端口被占用,Web?server?failed?to?start.Port?was?already?in?use.,本文給大家分享解決方案,分為linux系統(tǒng)和windows系統(tǒng)解決方案,需要的朋友可以參考下2023-07-07
Java多線程場景解析volatile和AtomicLong區(qū)別原理
這篇文章主要為大家介紹了Java中volatile和AtomicLong的區(qū)別原理示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-09-09

