MyBatis multi-data source configuration (read-write separation)
First of all, the most direct way to use the configuration in this article may be very troublesome to actually use.
There may be multiple combinations in actual applications. You can understand the meaning of this article and do not use it rigidly.
Possible situations with multiple data sources
1. Master and Slave
Usually, it is the case where MySQL has one master and multiple slaves. The example in this article is the case where the master and slaves are, but there are only two data sources, so it is not too troublesome to use direct configuration, but it is not conducive to subsequent expansion. It is mainly used as an example to illustrate. Please consider it carefully in actual operation.
2. Dividing the library
When business independence is strong and data volume is large, in order to improve concurrency, tables may be divided. After the database is divided, each database needs to configure a data source.
In this case, you can refer to this article, but it is necessary to note that the mapper corresponding to each database should be conveniently distinguished and configured under different packages.
In addition, when there are database partitions, there will be master-slave cases. If you have too many database slave libraries, please refer to the methods provided above, or find other ways to solve the problem.
Mapper subcontract
In the case of partitioning, the mappers of different databases must be placed under different packages.
In the case of master and slave, the same mapper will be read and written at the same time. It is not appropriate to create two, just use the same one. However, in this case, it is necessary to note that Spring automatically generates the name of the Mapper and the type is the same, so it cannot be directly injected into the Mapper interface. It needs to be solved through SqlSession.
Spring basic configuration
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 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"/>
This file mainly introduces spring-datasource-master.xml and 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 http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="dataSourceMaster" 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" > <property name="dataSource" ref="dataSourceMaster"/> <property name="mapperLocations"> <array> <value>classpath:mapper/*.xml</value> </array> </are> </bean> <bean> <bean> <property name="basePackage" value="com.isea533.mybatis.mapper"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory1"/> </bean> <bean id="sqlSessionMaster" 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="get*" read-only="true"/> <tx:method name="*"/> </tx:attributes> </tx:advice> <bean id="transactionManager1" > <property name="dataSource" ref="dataSourceMaster"/> </bean></beans>spring-datasource-slave.xml
There is little difference between it and master, mainly because there is a difference between the id name and the data source configuration.
<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 http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="dataSourceSlave" 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" > <property name="dataSource" ref="dataSourceSlave"/> <property name="mapperLocations"> <array> <value>classpath:mapper/*.xml</value> </array> </are> </bean> <bean> <bean> <property name="basePackage" value="com.isea533.mybatis.mapper"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory2"/> </bean> <bean id="sqlSessionSlave" 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" > <property name="dataSource" ref="dataSourceSlave"/> </bean></beans>It should be noted here that <tx:method name="*" read-only="true"/> is read-only. If it is not a slave library, you can configure it according to the main library.
In the following code:
<bean> <property name="basePackage" value="com.isea533.mybatis.mapper"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory2"/></bean>
Different sqlSessionFactory must be specified through sqlSessionFactoryBeanName.
config.properties
# Database Configuration - Mastermaster.jdbc.driverClass = com.mysql.jdbc.Drivermaster.jdbc.url = jdbc:mysql://192.168.1.11:3306/testmaster.jdbc.user = rootmaster.jdbc.password = jj# - Slaveslave.jdbc.driverClass = com.mysql.jdbc.Driverslave.jdbc.url = jdbc:mysql://192.168.1.22:3306/testslave.jdbc.user = rootslave.jdbc.password = jj
Using Mapper
This is set for the master and slave situation. The two configuration scan mappers are the same, so they cannot be directly injected, so they need to be injected through the troublesome method below.
@Servicepublic 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); }}Because sqlSession can be distinguished by name, we get the mapper from sqlSession.
In addition, if you need to consider when writing and reading in the same transaction, you need to use the same writeMapper so that the latest data in the transaction can be obtained when reading.
The above is the situation of the master and slave.
In the case of library partition, since different mappers are under different packages, you can directly inject the mapper using @Resource or @Autowired, and there is no need to obtain it through sqlSession.
This article is just a reference for multiple data sources. Please consider it according to your own situation when applying it in practice.
In the future, I will use my spare time to try to develop plug-ins that can automatically switch data sources based on this article and the two related links above to MySql multiple data sources. Because I am not very familiar with the practical application in this area, I welcome everyone to leave a message to share their own solutions. The more I know about these, the more likely it is to develop a general data source switching plug-in.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.