SpringBoot、MyBatis配置多数据源XML方法

本文介绍了在一个项目中配置和使用两个独立数据库的方法,包括修改配置文件以支持多数据源、配置MyBatis以区分不同数据源,以及通过测试验证配置的有效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载请注明来源-作者@loongshawn:http://blog.youkuaiyun.com/loongshawn/article/details/52164730

1、介绍

开发中有时候会碰到使用多个数据源的情况,这种情况也分两种不同的业务场景:

(1)、多个数据源是各自独立的,可以把它当作不同的项目来开发。比如一个是业务1的数据库,另一个是业务2的数据库。

(2)、多个数据源之间是主从关系(master-slave),其中一个数据库是master库,另外几个是slave库,从库需要同步主库的更新及变化。

2、背景

当前我的业务是在同一个工程中,接入另外一个数据库,提供计算与API服务,与当前工程所使用的库没有关联,两个数据库独立,所以我只需要针对上述场景(1)调整配置即可。

3、配置

3.1、修改application-dev.properties文件

修改application-dev.properties文件,新增数据库配置地址及权限。

单一库时的配置:

# mysql第一数据源
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test_2
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.initialSize=10
spring.datasource.maxActive=99
spring.datasource.maxIdle=20
spring.datasource.minIdle=9
spring.datasource.removeAbandoned=true
spring.datasource.removeAbandonedTimeout=180
spring.datasource.maxWait=60000
spring.datasource.validationQuery=select 1 from dual
spring.datasource.testOnBorrow=true
spring.datasource.connectionProperties=clientEncoding=UTF-8
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

新增一个库后的配置:

# mysql第一数据源
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test_1
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.initialSize=10
spring.datasource.maxActive=99
spring.datasource.maxIdle=20
spring.datasource.minIdle=9
spring.datasource.removeAbandoned=true
spring.datasource.removeAbandonedTimeout=180
spring.datasource.maxWait=60000
spring.datasource.validationQuery=select 1 from dual
spring.datasource.testOnBorrow=true
spring.datasource.connectionProperties=clientEncoding=UTF-8

# mysql第二数据源
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test_2
spring.datasource.username=test
spring.datasource.password=test
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

说明:第二个数据源中只需要修改数据库地址及权限即可,数据库的基本配置参数可与数据源一公用。

3.2、修改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:task="http://www.springframework.org/schema/task"
    xmlns:context="http://www.springframework.org/schema/context"
    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/task
    http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <bean id="properties"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:spring/config/application-dev.properties</value>
            </list>
        </property>
        <property name="ignoreUnresolvablePlaceholders" value="true" />
    </bean>

    <bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource"
        destroy-method="close">
        <property name="driverClassName" value="${spring.datasource.driverClassName}" />
        <property name="url" value="${spring.datasource.url}" />
        <property name="username" value="${spring.datasource.username}" />
        <property name="password" value="${spring.datasource.password}" />
        <property name="initialSize" value="${spring.datasource.initialSize}" />
        <property name="maxActive" value="${spring.datasource.maxActive}" />
        <property name="maxIdle" value="${spring.datasource.maxIdle}" />
        <property name="minIdle" value="${spring.datasource.minIdle}" />
        <property name="removeAbandoned" value="${spring.datasource.removeAbandoned}" />
        <property name="removeAbandonedTimeout" value="${spring.datasource.removeAbandonedTimeout}" />
        <property name="maxWait" value="${spring.datasource.maxWait}" />
        <property name="validationQuery" value="${spring.datasource.validationQuery}" />
        <property name="testOnBorrow" value="${spring.datasource.testOnBorrow}" />
        <property name="connectionProperties" value="${spring.datasource.connectionProperties}" />
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mapperLocations" value="classpath*:com/autonavi/dao/impl/mapper/*.xml" />
        <property name="typeAliasesPackage" value="com.autonavi.domain" />
    </bean>

    <!-- mybatis.spring自动映射 -->
    <bean id="mybatisMapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.autonavi.dao.impl.mapper" />
        <!--<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />-->
    </bean>

    <bean id="springContextUtil" class="com.autonavi.utils.MyApplicationContextUtil"/>

    <bean id="appErrorController" class="com.autonavi.controller.AppErrorController"/>

    <!-- Enables the Spring Task @Scheduled programming model -->
    <task:executor id="executor" pool-size="10" />
    <task:scheduler id="scheduler" pool-size="20" />
    <task:annotation-driven executor="executor" scheduler="scheduler" />

    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="org.apache.shiro.authz.UnauthenticatedException">pages/403</prop>
                <prop key="org.apache.shiro.authz.UnauthorizedException">pages/403</prop>
                <prop key="org.apache.shiro.authc.LockedAccountException">pages/locked</prop>
                <prop key="java.lang.Throwable">pages/500</prop>
            </props>
        </property>
    </bean>
</beans>

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73

新增数据源后的文件内容:

<?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:task="http://www.springframework.org/schema/task"
    xmlns:context="http://www.springframework.org/schema/context"
    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/task
    http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <bean id="properties"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:spring/config/application-dev.properties</value>
            </list>
        </property>
        <property name="ignoreUnresolvablePlaceholders" value="true" />
    </bean>

    <bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource"
        destroy-method="close">
        <property name="driverClassName" value="${spring.datasource.driverClassName}" />
        <property name="url" value="${spring.datasource.url}" />
        <property name="username" value="${spring.datasource.username}" />
        <property name="password" value="${spring.datasource.password}" />
        <property name="initialSize" value="${spring.datasource.initialSize}" />
        <property name="maxActive" value="${spring.datasource.maxActive}" />
        <property name="maxIdle" value="${spring.datasource.maxIdle}" />
        <property name="minIdle" value="${spring.datasource.minIdle}" />
        <property name="removeAbandoned" value="${spring.datasource.removeAbandoned}" />
        <property name="removeAbandonedTimeout" value="${spring.datasource.removeAbandonedTimeout}" />
        <property name="maxWait" value="${spring.datasource.maxWait}" />
        <property name="validationQuery" value="${spring.datasource.validationQuery}" />
        <property name="testOnBorrow" value="${spring.datasource.testOnBorrow}" />
        <property name="connectionProperties" value="${spring.datasource.connectionProperties}" />
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mapperLocations" value="classpath*:com/autonavi/dao/impl/mapper/*.xml" />
        <property name="typeAliasesPackage" value="com.autonavi.domain" />
    </bean>

    <!-- mybatis.spring自动映射 -->
    <bean id="mybatisMapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.autonavi.dao.impl.mapper" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
    </bean>

    <!-- 第二个数据源配置 -->   
    <bean id="dataSource2" class="org.apache.tomcat.jdbc.pool.DataSource"
        destroy-method="close">
        <property name="driverClassName" value="${spring.datasource.driverClassName}" />
        <property name="url" value="${spring.datasource.url2}" />
        <property name="username" value="${spring.datasource.username2}" />
        <property name="password" value="${spring.datasource.password2}" />
        <property name="initialSize" value="${spring.datasource.initialSize}" />
        <property name="maxActive" value="${spring.datasource.maxActive}" />
        <property name="maxIdle" value="${spring.datasource.maxIdle}" />
        <property name="minIdle" value="${spring.datasource.minIdle}" />
        <property name="removeAbandoned" value="${spring.datasource.removeAbandoned}" />
        <property name="removeAbandonedTimeout" value="${spring.datasource.removeAbandonedTimeout}" />
        <property name="maxWait" value="${spring.datasource.maxWait}" />
        <property name="validationQuery" value="${spring.datasource.validationQuery}" />
        <property name="testOnBorrow" value="${spring.datasource.testOnBorrow}" />
        <property name="connectionProperties" value="${spring.datasource.connectionProperties}" />
    </bean>

    <bean id="sqlSessionFactory2" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource2" />
        <property name="mapperLocations" value="classpath*:com/autonavi/dao/impl/mapper2/*.xml" />
        <property name="typeAliasesPackage" value="com.autonavi.domain" />
    </bean>

    <!-- mybatis.spring自动映射 -->
    <bean id="mybatisMapperScanner2" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.autonavi.dao.impl.mapper2.pmp" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory2" />
    </bean>

    <bean id="springContextUtil" class="com.autonavi.utils.MyApplicationContextUtil"/>

    <bean id="appErrorController" class="com.autonavi.controller.AppErrorController"/>

    <!-- Enables the Spring Task @Scheduled programming model -->
    <task:executor id="executor" pool-size="10" />
    <task:scheduler id="scheduler" pool-size="20" />
    <task:annotation-driven executor="executor" scheduler="scheduler" />

    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="org.apache.shiro.authz.UnauthenticatedException">pages/403</prop>
                <prop key="org.apache.shiro.authz.UnauthorizedException">pages/403</prop>
                <prop key="org.apache.shiro.authc.LockedAccountException">pages/locked</prop>
                <prop key="java.lang.Throwable">pages/500</prop>
            </props>
        </property>
    </bean>

</beans>

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105

其中新增的配置如下,同时大家需要注意以下几点:

  • dataSource2、sqlSessionFactory2、mybatisMapperScanner2的名字改写,与数据源一不要一样。
  • 在mybatisMapperScanner、mybatisMapperScanner2中添加属性sqlSessionFactoryBeanName,值为sqlSessionFactory、sqlSessionFactory2。

下面为新增的数据源配置:

<!-- 第二个数据源配置 -->   
    <bean id="dataSource2" class="org.apache.tomcat.jdbc.pool.DataSource"
        destroy-method="close">
        <property name="driverClassName" value="${spring.datasource.driverClassName}" />
        <property name="url" value="${spring.datasource.url2}" />
        <property name="username" value="${spring.datasource.username2}" />
        <property name="password" value="${spring.datasource.password2}" />
        <property name="initialSize" value="${spring.datasource.initialSize}" />
        <property name="maxActive" value="${spring.datasource.maxActive}" />
        <property name="maxIdle" value="${spring.datasource.maxIdle}" />
        <property name="minIdle" value="${spring.datasource.minIdle}" />
        <property name="removeAbandoned" value="${spring.datasource.removeAbandoned}" />
        <property name="removeAbandonedTimeout" value="${spring.datasource.removeAbandonedTimeout}" />
        <property name="maxWait" value="${spring.datasource.maxWait}" />
        <property name="validationQuery" value="${spring.datasource.validationQuery}" />
        <property name="testOnBorrow" value="${spring.datasource.testOnBorrow}" />
        <property name="connectionProperties" value="${spring.datasource.connectionProperties}" />
    </bean>

    <bean id="sqlSessionFactory2" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource2" />
        <property name="mapperLocations" value="classpath*:com/autonavi/dao/impl/mapper2/*.xml" />
        <property name="typeAliasesPackage" value="com.autonavi.domain" />
    </bean>

    <!-- mybatis.spring自动映射 -->
    <bean id="mybatisMapperScanner2" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.autonavi.dao.impl.mapper2.pmp" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory2" />
    </bean>
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

如上所示,我们分别配置了两个 dataSource,两个sqlSessionFactory,两个mybatisMapperScanner,以及关键的地方在于MapperScannerConfigurer 的配置——使用sqlSessionFactoryBeanName属性,注入不同的sqlSessionFactory的名称,这样的话,就为不同的数据库对应的 mapper 接口注入了对应的 sqlSessionFactory。

4、测试

4.1、测试要求

工程运行后,可同时连接2个数据库进行相关业务操作。

4.2、新建测试用例

新建测试类QuarterTest,其中quarterMapper来自数据源一,projectMapper来自数据源二:

public class QuarterTest {

    private static final Logger logger = LoggerFactory.getLogger(QuarterTest.class);

    @Autowired
    private QuarterMapper quarterMapper;

    public void action(){

        // no.1 初始化工作       
        quarterMapper = MyApplicationContextUtil.getBean("quarterMapper");  
        ProjectMapper projectMapper = MyApplicationContextUtil.getBean("projectMapper");    

        List<Version> list1 = quarterMapper.selectQuarters();
        List<Version> list2 = projectMapper.selectQuarters();

        logger.info("数据源1,size:{}",list1.size());
        for(Version quarter : list1){ 

            logger.info("QuarterTest.method [action]: info id:{},version_name:{},year:{},fiscal_year:{}", quarter.getId(),quarter.getVersion_name(),quarter.getYear(),quarter.getFiscal_year());
        }
        logger.info("数据源2,size:{}",list2.size());
        for(Version quarter : list2){

            logger.info("QuarterTest.method [action]: info id:{},version_name:{},year:{},fiscal_year:{}", quarter.getId(),quarter.getVersion_name(),quarter.getYear(),quarter.getFiscal_year());
        }
    }

}

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

4.3、测试结果

(1)工程运行正常

这里写图片描述

这里写图片描述

(2)任务执行结果

第一个数据源查询结果为45条记录:

这里写图片描述

第二个数据源查询结果为29条记录:

这里写图片描述

Console输出结果:

2016-08-09-14-22 [scheduler-3] [com.autonavi.task.ScheduledTasks] [INFO] - ScheduledTest.executeFileDownLoadTask 定时任务1:17,name:scheduler-3
     2016-08-09-14-22 [scheduler-2] [java.sql.Connection] [DEBUG] - ooo Using Connection [ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@56b5dd08]]]
     2016-08-09-14-22 [scheduler-2] [java.sql.Connection] [DEBUG] - ==>  Preparing: SELECT id, version_name, year, fiscal_year FROM version_table 
     2016-08-09-14-22 [scheduler-2] [java.sql.PreparedStatement] [DEBUG] - ==> Parameters: 
     2016-08-09-14-22 [scheduler-2] [java.sql.Connection] [DEBUG] - ooo Using Connection [ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@65e921a2]]]
     2016-08-09-14-22 [scheduler-2] [java.sql.Connection] [DEBUG] - ==>  Preparing: SELECT id, version_name, year, fiscal_year FROM version_table 
     2016-08-09-14-22 [scheduler-2] [java.sql.PreparedStatement] [DEBUG] - ==> Parameters: 
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - 数据源1,size:45
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:1,version_name:2016Q1,year:2016,fiscal_year:2015
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:2,version_name:2016Q2,year:2016,fiscal_year:2016
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:3,version_name:2016Q3,year:2016,fiscal_year:2016
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:4,version_name:2016Q4,year:2016,fiscal_year:2016
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:5,version_name:2017Q1,year:2017,fiscal_year:2016
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:6,version_name:2017Q2,year:2017,fiscal_year:2017
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:7,version_name:2017Q3,year:2017,fiscal_year:2017
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:8,version_name:2017Q4,year:2017,fiscal_year:2017
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:9,version_name:2018Q1,year:2018,fiscal_year:2017
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:10,version_name:2018Q2,year:2018,fiscal_year:2018
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:11,version_name:2018Q3,year:2018,fiscal_year:2018
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:12,version_name:2018Q4,year:2018,fiscal_year:2018
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:13,version_name:2019Q1,year:2019,fiscal_year:2018
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:14,version_name:2019Q2,year:2019,fiscal_year:2019
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:15,version_name:2019Q3,year:2019,fiscal_year:2019
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:16,version_name:2019Q4,year:2019,fiscal_year:2019
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:17,version_name:2020Q1,year:2020,fiscal_year:2019
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:18,version_name:2020Q2,year:2020,fiscal_year:2020
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:19,version_name:2020Q3,year:2020,fiscal_year:2020
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:20,version_name:2020Q4,year:2020,fiscal_year:2020
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:21,version_name:2021Q1,year:2021,fiscal_year:2020
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:22,version_name:2021Q2,year:2021,fiscal_year:2021
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:23,version_name:2021Q3,year:2021,fiscal_year:2021
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:24,version_name:2021Q4,year:2021,fiscal_year:2021
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:25,version_name:2022Q1,year:2022,fiscal_year:2021
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:26,version_name:2022Q2,year:2022,fiscal_year:2022
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:27,version_name:2022Q3,year:2022,fiscal_year:2022
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:28,version_name:2022Q4,year:2022,fiscal_year:2022
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:29,version_name:2023Q1,year:2023,fiscal_year:2022
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:30,version_name:2023Q2,year:2023,fiscal_year:2023
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:31,version_name:2023Q3,year:2023,fiscal_year:2023
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:32,version_name:2023Q4,year:2023,fiscal_year:2023
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:33,version_name:2024Q1,year:2024,fiscal_year:2023
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:34,version_name:2024Q2,year:2024,fiscal_year:2024
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:35,version_name:2024Q3,year:2024,fiscal_year:2024
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:36,version_name:2024Q4,year:2024,fiscal_year:2024
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:37,version_name:2025Q1,year:2025,fiscal_year:2024
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:38,version_name:2025Q2,year:2025,fiscal_year:2025
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:39,version_name:2025Q3,year:2025,fiscal_year:2025
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:40,version_name:2025Q4,year:2025,fiscal_year:2025
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:41,version_name:2026Q1,year:2026,fiscal_year:2025
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:42,version_name:2026Q2,year:2026,fiscal_year:2026
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:43,version_name:2026Q3,year:2026,fiscal_year:2026
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:44,version_name:2026Q4,year:2026,fiscal_year:2026
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:45,version_name:2027Q1,year:2027,fiscal_year:2026
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - 数据源2,size:29
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:1,version_name:2016Q1,year:2016,fiscal_year:2015
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:2,version_name:2016Q2,year:2016,fiscal_year:2016
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:3,version_name:2016Q3,year:2016,fiscal_year:2016
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:4,version_name:2016Q4,year:2016,fiscal_year:2016
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:5,version_name:2017Q1,year:2017,fiscal_year:2016
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:6,version_name:2017Q2,year:2017,fiscal_year:2017
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:7,version_name:2017Q3,year:2017,fiscal_year:2017
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:8,version_name:2017Q4,year:2017,fiscal_year:2017
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:9,version_name:2018Q1,year:2018,fiscal_year:2017
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:10,version_name:2018Q2,year:2018,fiscal_year:2018
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:11,version_name:2018Q3,year:2018,fiscal_year:2018
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:12,version_name:2018Q4,year:2018,fiscal_year:2018
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:13,version_name:2019Q1,year:2019,fiscal_year:2018
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:14,version_name:2019Q2,year:2019,fiscal_year:2019
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:15,version_name:2019Q3,year:2019,fiscal_year:2019
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:16,version_name:2019Q4,year:2019,fiscal_year:2019
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:17,version_name:2020Q1,year:2020,fiscal_year:2019
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:18,version_name:2020Q2,year:2020,fiscal_year:2020
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:19,version_name:2020Q3,year:2020,fiscal_year:2020
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:20,version_name:2020Q4,year:2020,fiscal_year:2020
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:21,version_name:2021Q1,year:2021,fiscal_year:2020
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:22,version_name:2021Q2,year:2021,fiscal_year:2021
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:23,version_name:2021Q3,year:2021,fiscal_year:2021
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:24,version_name:2021Q4,year:2021,fiscal_year:2021
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:25,version_name:2022Q1,year:2022,fiscal_year:2021
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:26,version_name:2022Q2,year:2022,fiscal_year:2022
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:27,version_name:2022Q3,year:2022,fiscal_year:2022
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:28,version_name:2022Q4,year:2022,fiscal_year:2022
     2016-08-09-14-22 [scheduler-2] [com.autonavi.method.pmp.QuarterTest] [INFO] - QuarterTest.method [action]: info id:29,version_name:2023Q1,year:2023,fiscal_year:2022

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84

5、总结

上面的这种多数据源配置是不支持分布式事务的,也就是同一个事务中,不能操作多个数据库。这种配置方式的优点是很简单,但是却不灵活,需要依据业务场景来选择,如我当前的业务场景通过上述配置即可快速达成要求。

对于master-slave类型的多数据源配置而言不太适应,master-slave性的多数据源的配置,需要特别灵活,需要根据业务的类型进行细致的配置。比如对于一些耗时特别大的select语句,我们希望放到slave上执行,而对于update,delete等操作肯定是只能在master上执行的,另外对于一些实时性要求很高的select语句,我们也可能需要放到master上执行——比如一个场景是打游戏过程中,去商城购买一件兵器,购买操作的很定是master,同时购买完成之后,需要重新查询出我所拥有的兵器和金币,那么这个查询可能也需要防止master上执行,而不能放在slave上去执行,因为slave上可能存在延时,我们可不希望玩家发现购买成功之后,在背包中却找不到兵器的情况出现。

至于如何解决这种场景下的多数据库源配置,还有待继续学习。在此我整理了部分网络上的解决方案:

对于master-slave类型的多数据源的配置,需要根据业务来进行灵活的配置,哪些select可以放到slave上,哪些select不能放到slave上。所以上面的那种所数据源的配置就不太适应了,需要采用另外一套方式。即,利用基于 AbstractRoutingDataSource 和 AOP 的多数据源的配置。

其基本原理是,自己定义一个DataSource类ThreadLocalRountingDataSource,来继承AbstractRoutingDataSource,然后在配置文件中向ThreadLocalRountingDataSource注入 master 和 slave 的数据源,然后通过 AOP 来灵活配置,在哪些地方选择 master 数据源,在哪些地方需要选择 slave数据源。具体实现将会在后续文章中说明。

<think>首先,用户的问题是:“我想了解如何在SpringBoot项目中使用MyBatis配置多数据源请问springbootmybatis多数据源配置教程”。根据系统指令,我需要基于提供的引用(引用[1]到[4])来回答这个问题。系统指令关键点:-所有行内数学表达式使用$...$格式(但这里可能不需要数学表达式,因为主题是SpringBootMyBatis)。-独立公式使用$$...$$格式(同样,可能不适用)。-LaTeX语法正确。-使用中文回答。-生成相关问题。-在引用的段落末尾自然地添加引用标识。-回答结构清晰,帮助用户逐步解决问题。-参考用户上一次的问题:用户提到参考站内引用,但用户的初始问题就是如何配置多数据源。提供的引用摘要:-[^1]:SpringBoot多数据源配置教程,自动切换数据源的项目地址。-[^2]:SpringBoot2.x基础教程:MyBatis多数据源配置,来自博客didispace.com。-[^3]:SpringBoot整合MyBatis多数据源配置了application.properties中的两个数据源。-[^4]:SpringBoot集成MyBatis配置多数据源详细教程,包括Mapper接口和XML文件的组织。我需要基于这些引用来构建回答。核心主题是配置多数据源,涉及:1.配置数据源在application.properties(或.yml)中。2.定义多个DataSourcebean。3.配置MyBatis来使用这些数据源。4.组织Mapper接口和XML映射文件。逐步回答结构:1.**引言**:简要介绍SpringBootMyBatis配置多数据源的重要性或场景。2.**步骤分解**:分步解释配置过程。3.**参考引用的部分**:自然地融入引用内容。4.**代码示例**:提供代码片段展示配置。5.**相关问题**:生成相关问题。6.**引用标识**:在相关的结尾处添加引用标识。回答必须是中文。最终输出格式:按照用户可见层,结构清晰。生成相关问题:在回答末尾,添加相关问题,用§§相关问题§§标记。现在,规划回答内容:**步骤:**1.**配置数据源属性**:在application.properties中定义多个数据源的连接信息。示例来自[^3]:```spring.datasource.one.url=jdbc:mysql:///zmfspring.datasource.one.username=rootspring.datasource.one.password=rootspring.datasource.one.driver-class-name=com.mysql.jdbc.Driver#类似定义第二个数据源spring.datasource.two.url=jdbc:mysql:///test...```添加引用标识[^3]。2.**创建DataSourcebeans**:在配置类中定义多个DataSourcebean。从引用中推测,使用@Configuration注解类,定义@Bean方法。例如:```java@ConfigurationpublicclassDataSourceConfig{@Bean@ConfigurationProperties(prefix="spring.datasource.one")publicDataSourcedataSourceOne(){returnDataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix="spring.datasource.two")publicDataSourcedataSourceTwo(){returnDataSourceBuilder.create().build();}}```参考[^3],它提到提供两个DataSource。3.**配置MyBatisSessionFactory**:为每个数据源创建SqlSessionFactory和SqlSessionTemplate。引用[^4]提到在Mapper接口和XML中组织不同包。-例如,为每个数据源创建单独的配置:```java@Configuration@MapperScan(basePackages="com.example.mapper.one",sqlSessionTemplateRef="sqlSessionTemplateOne")publicclassMyBatisConfigOne{@BeanpublicSqlSessionFactorysqlSessionFactoryOne(DataSourcedataSourceOne)throwsException{SqlSessionFactoryBeanfactoryBean=newSqlSessionFactoryBean();factoryBean.setDataSource(dataSourceOne);factoryBean.setMapperLocations(newPathMatchingResourcePatternResolver().getResources("classpath:mapper/one/*.xml"));returnfactoryBean.getObject();}@BeanpublicSqlSessionTemplatesqlSessionTemplateOne(SqlSessionFactorysqlSessionFactoryOne){returnnewSqlSessionTemplate(sqlSessionFactoryOne);}}```类似定义第二个配置。4.**组织Mapper接口**:引用[^4]:在com.chenyun.cloud.mapper.wxdev和com.chenyun.cloud.mapper.platform包中提供不同Mapper接口,以及在resources目录下创建不同XML映射文件。添加引用[^4]。5.**自动切换数据源**:引用[^1]提到自动切换数据源,可能使用AOP或ThreadLocal来管理数据源路由。完整回答:-开头:解释什么是多数据源配置。-步骤1:配置属性。-步骤2:定义DataSourcebeans。-步骤3:配置MyBatisSqlSessionFactory和Template。-步骤4:使用@MapperScan指定不同的包。-结尾:总结或注意事项。相关问题生成:基于主题,生成如:1.如何实现多数据源的动态切换?2.SpringBoot中如何解决多数据源事务问题?3.MyBatis多数据源配置常见问题有哪些?添加引用标识:-在提到具体内容后添加,例如:"配置属性如引用[^3]所示。"</think> ### Spring Boot中配置MyBatis多数据源的分步教程 在Spring Boot项目中配置MyBatis多数据源,主要涉及定义多个数据源、创建独立的SqlSessionFactory实例,并通过包路径或Mapper接口分离不同数据源的SQL操作。以下是基于参考引用的详细步骤指南: #### **步骤1:配置数据源属性(`application.properties`)** 在配置文件中定义多个数据源的连接信息。以下示例配置两个数据源(`one` 和 `two`),分别指向不同数据库: ```properties # 数据源 one 的配置 spring.datasource.one.url=jdbc:mysql:///zmf spring.datasource.one.username=root spring.datasource.one.password=root spring.datasource.one.driver-class-name=com.mysql.jdbc.Driver # 数据源 two 的配置 spring.datasource.two.url=jdbc:mysql:///test spring.datasource.two.username=root spring.datasource.two.password=root spring.datasource.two.driver-class-name=com.mysql.jdbc.Driver ``` 关键点: - 使用前缀(如`spring.datasource.one`)区分不同数据源。 - 支持第三方连接池(如Druid),通过`type`属性指定[^3]。 #### **步骤2:创建多个DataSource Bean** 在配置类中定义多个`DataSource` Bean,分别对应配置文件中的属性: ```java @Configuration public class DataSourceConfig { // 数据源 one @Bean @ConfigurationProperties(prefix = "spring.datasource.one") public DataSource dataSourceOne() { return DataSourceBuilder.create().build(); } // 数据源 two @Bean @ConfigurationProperties(prefix = "spring.datasource.two") public DataSource dataSourceTwo() { return DataSourceBuilder.create().build(); } } ``` 说明:`@ConfigurationProperties`自动绑定属性到Bean属性[^3]。 #### **步骤3:配置独立的SqlSessionFactory和SqlSessionTemplate** 为每个数据源创建单独的`SqlSessionFactory`和`SqlSessionTemplate`,确保SQL会话隔离: ```java @Configuration @MapperScan(basePackages = "com.example.mapper.one", sqlSessionTemplateRef = "sqlSessionTemplateOne") public class MyBatisConfigOne { @Autowired private DataSource dataSourceOne; @Bean public SqlSessionFactory sqlSessionFactoryOne() throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSourceOne); // 指定Mapper XML路径(可选) factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/one/*.xml")); return factoryBean.getObject(); } @Bean public SqlSessionTemplate sqlSessionTemplateOne() throws Exception { return new SqlSessionTemplate(sqlSessionFactoryOne()); } } // 类似配置第二个数据源(如MyBatisConfigTwo),修改basePackages和路径 ``` 要点: - `@MapperScan`的`basePackages`指定Mapper接口的包路径,确保不同数据源接口隔离(如`com.example.mapper.one`和`com.example.mapper.two`)[^4]。 - XML映射文件建议放在不同目录(如`resources/mapper/one`和`resources/mapper/two`)[^4]。 #### **步骤4:实现自动数据源切换(可选)** 引用[^1]提到的项目实现了自动切换逻辑: - 使用Spring AOP或自定义注解,通过ThreadLocal动态切换数据源。 - 示例核心逻辑: ```java public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceKey(); // 从ThreadLocal获取数据源标识 } } ``` - 可在[项目地址](https://gitcode.com/gh_mirrors/spr/springboot-multiple-dataSources)查看完整代码[^1]。 #### **注意事项** 1. **事务管理**:默认Spring事务仅支持单个数据源。如需多数据源事务,需引入JTA或Atomikos。 2. **依赖冲突**:确保`spring-boot-starter-jdbc`和`mybatis-spring-boot-starter`版本兼容[^2]。 3. **测试**:启动时检查日志确认数据源初始化成功。 通过以上步骤,即可实现多数据源的隔离操作。例如,访问`com.example.mapper.one`包中的Mapper会使用数据源one,而`com.example.mapper.two`则使用数据源two[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值