1.SpringMVC整合MyBatis及多数据源配置

1.1pom.xml文件引入mybatis配置

<!-- mysql -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql.version}</version>
    </dependency>

    <!-- myBatis -->

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>${mybatis-version}</version>
    </dependency>

    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>${mybatis-spring-version}</version>
    </dependency>


    <dependency>
      <groupId>com.mchange</groupId>
      <artifactId>c3p0</artifactId>
      <version>${c3p0.version}</version>
    </dependency>

1.2 /resources目录添加mybatis-config.xml配置文件以及mybatis目录

java aop配置多数据源 设置自动重连逻辑_bc

这个工程我配置了两个数据源,所以mybatis目录下的Mapper文件根据不同数据源分别放在不同目录下,这样编译扫描Mapper文件。

mybatis-config.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD SQL Map Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--
 |   plugins在配置文件中的位置必须符合要求,否则会报错,顺序如下:
 |   properties?, settings?,
 |   typeAliases?, typeHandlers?,
 |   objectFactory?,objectWrapperFactory?,
 |   plugins?,
 |   environments?, databaseIdProvider?, mappers?
 |-->
<configuration>
    <!--
     | 全局配置设置
     |
     | 可配置选项                   默认值,     描述
     |
     | aggressiveLazyLoading       true,     当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。
     | multipleResultSetsEnabled   true,     允许和不允许单条语句返回多个数据集(取决于驱动需求)
     | useColumnLabel              true,     使用列标签代替列名称。不同的驱动器有不同的作法。参考一下驱动器文档,或者用这两个不同的选项进行测试一下。
     | useGeneratedKeys            false,    允许JDBC 生成主键。需要驱动器支持。如果设为了true,这个设置将强制使用被生成的主键,有一些驱动器不兼容不过仍然可以执行。
     | autoMappingBehavior         PARTIAL,  指定MyBatis 是否并且如何来自动映射数据表字段与对象的属性。PARTIAL将只自动映射简单的,没有嵌套的结果。FULL 将自动映射所有复杂的结果。
     | defaultExecutorType         SIMPLE,   配置和设定执行器,SIMPLE 执行器执行其它语句。REUSE 执行器可能重复使用prepared statements 语句,BATCH执行器可以重复执行语句和批量更新。
     | defaultStatementTimeout     null,     设置一个时限,以决定让驱动器等待数据库回应的多长时间为超时
     | -->
    <settings>
        <!-- 这个配置使全局的映射器启用或禁用缓存 -->
        <setting name="cacheEnabled" value="true"/>
        <!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="multipleResultSetsEnabled" value="true"/>
        <setting name="useColumnLabel" value="true"/>
        <setting name="defaultExecutorType" value="REUSE"/>
        <setting name="defaultStatementTimeout" value="25000"/>
    </settings>

</configuration>

Mapper.xml文件和Dao类要一一对应

Mapper.xml文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.test.dao.second.ChannelDao">
    <!--例子http://www.2cto.com/database/201409/338155.html-->

    <resultMap type="com.test.domain.ProductChannel" id="ChannelResult">
        <result column="channel" property="channel"/>
        <result column="name" property="name"/>
    </resultMap>

    <select id="getChannelList" resultMap="ChannelResult">
        select channel,name from tb_channel where deleted = 0 and length(name) > 0 and p_id = 91
        ORDER BY id
    </select>



</mapper>

namespace要指定对应的Dao类。Dao类内容如下:

package com.test.dao.second;

import com.test.domain.ProductChannel;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
 * Created by on 2017/12/27.
 */
@Mapper
public interface ChannelDao {

    List<ProductChannel> getChannelList();
}

1.3 spring-context.xml配置数据源

SpringMVC工程当中数据源的配置是写在spring-context.xml文件当中的。

<!-- Mapper文件扫描路径配置 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.xxxx.xxx.dao.first"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory1"/>
    </bean>

<!-- 数据库1配置 -->
    <bean id="sqlSessionFactory1" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="adminDataSource"/>
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:/mybatis/first/*Mapper.xml"/>
    </bean>

    <bean id="sqlSessionTemplate1" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory1"/>
        <constructor-arg index="1" value="BATCH"/>
    </bean>


    <bean id="transactionManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="adminDataSource"></property>
    </bean>

    <bean id="adminDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
          destroy-method="close">
        <property name="driverClass" value="${admin-jdbc.driverClassName}" />
        <property name="jdbcUrl" value="${admin-jdbc.url}" />
        <property name="user" value="${admin-jdbc.user}" />
        <property name="password" value="${admin-jdbc.pass}" />
        <!--连接池中保留的最小连接数。 -->
        <property name="minPoolSize" value="${c3p0.minPoolSize}" />
        <!--连接池中保留的最大连接数。Default: 15 -->
        <property name="maxPoolSize" value="${c3p0.maxPoolSize}" />
        <!--最大空闲时间,1800秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
        <property name="maxIdleTime" value="${c3p0.maxIdleTime}" />
        <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
        <property name="acquireIncrement" value="${c3p0.acquireIncrement}" />
        <property name="initialPoolSize" value="${c3p0.initialPoolSize}" />
        <!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
        <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}" />
        <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
        <property name="acquireRetryAttempts" value="${c3p0.acquireRetryAttempts}" />
        <property name="testConnectionOnCheckout" value="${c3p0.testConnectionOnCheckout}" />
    </bean>


    <tx:advice id="adminTxAdvice" transaction-manager="transactionManager1">
        <tx:attributes>
            <!-- 以下方法必须在事物中执行,一般增、删、改操作需要配置事务 -->
            <!-- REQUIRED 如果当前有事务环境就加入当前正在执行的事务环境,如果当前没有事务,就新建一个事务。 -->
            <tx:method name="create*" propagation="REQUIRED"/>
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="add*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="remove*" propagation="REQUIRED"/>
            <tx:method name="del*" propagation="REQUIRED"/>
            <tx:method name="import*" propagation="REQUIRED"/>
            <tx:method name="modify*" propagation="REQUIRED"/>
            <tx:method name="finish*" propagation="REQUIRED"/>
            <tx:method name="freeze*" propagation="REQUIRED"/>
            <tx:method name="edit*" propagation="REQUIRED"/>
            <tx:method name="up*" propagation="REQUIRED"/>
            <tx:method name="down*" propagation="REQUIRED"/>
            <tx:method name="select*" propagation="REQUIRED"/>
            <tx:method name="unselect*" propagation="REQUIRED"/>

            <!-- 以下方法以非事务方式执行,一般用于查询操作 -->
            <!-- 如果当前存在事务,就把当前事务挂起,等该方法以非事务的状态运行完,再继续原来的事务。 -->
            <!-- read-only="true" 表示只读 -->
            <tx:method name="*" read-only="false"/>
        </tx:attributes>
    </tx:advice>

其中${admin-jdbc.url}这些参数是从jdbc.properties配置文件中读取的,具体的配置在我的文章《SpringMVC和SpringBoot开发环境、生产环境的多环境配置》中有详细介绍。

SpringMVC的多数据源配置很简单,只要按照上面的方式再创建一组bean就行了,如下所示:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.xxxx.xxx.dao.second"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory2"/>
    </bean>

<!-- 数据库2配置 -->
    <bean id="sqlSessionFactory2" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="secondDataSource"/>
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <property name="mapperLocations" value="classpath:/mybatis/second/*Mapper.xml"/>
    </bean>

    <bean id="sqlSessionTemplate2" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory2"/>
        <constructor-arg index="1" value="BATCH"/>
    </bean>


    <bean id="transactionManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="secondDataSource"></property>
    </bean>

    <bean id="secondDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
          destroy-method="close">
        <property name="driverClass" value="${second-jdbc.driverClassName}" />
        <property name="jdbcUrl" value="${second-jdbc.url}" />
        <property name="user" value="${second-jdbc.user}" />
        <property name="password" value="${second-jdbc.pass}" />
        <!--连接池中保留的最小连接数。 -->
        <property name="minPoolSize" value="${c3p0.minPoolSize}" />
        <!--连接池中保留的最大连接数。Default: 15 -->
        <property name="maxPoolSize" value="${c3p0.maxPoolSize}" />
        <!--最大空闲时间,1800秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
        <property name="maxIdleTime" value="${c3p0.maxIdleTime}" />
        <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
        <property name="acquireIncrement" value="${c3p0.acquireIncrement}" />
        <property name="initialPoolSize" value="${c3p0.initialPoolSize}" />
        <!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
        <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}" />
        <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
        <property name="acquireRetryAttempts" value="${c3p0.acquireRetryAttempts}" />
        <property name="testConnectionOnCheckout" value="${c3p0.testConnectionOnCheckout}" />
    </bean>


    <tx:advice id="secondTxAdvice" transaction-manager="transactionManager2">
        <tx:attributes>
            <!-- 以下方法必须在事物中执行,一般增、删、改操作需要配置事务 -->
            <!-- REQUIRED 如果当前有事务环境就加入当前正在执行的事务环境,如果当前没有事务,就新建一个事务。 -->
            <tx:method name="create*" propagation="REQUIRED"/>
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="add*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="remove*" propagation="REQUIRED"/>
            <tx:method name="del*" propagation="REQUIRED"/>
            <tx:method name="import*" propagation="REQUIRED"/>
            <tx:method name="modify*" propagation="REQUIRED"/>
            <tx:method name="finish*" propagation="REQUIRED"/>
            <tx:method name="freeze*" propagation="REQUIRED"/>
            <tx:method name="edit*" propagation="REQUIRED"/>
            <tx:method name="up*" propagation="REQUIRED"/>
            <tx:method name="down*" propagation="REQUIRED"/>
            <tx:method name="select*" propagation="REQUIRED"/>
            <tx:method name="unselect*" propagation="REQUIRED"/>

            <!-- 以下方法以非事务方式执行,一般用于查询操作 -->
            <!-- 如果当前存在事务,就把当前事务挂起,等该方法以非事务的状态运行完,再继续原来的事务。 -->
            <!-- read-only="true" 表示只读 -->
            <tx:method name="*" read-only="false"/>
        </tx:attributes>
    </tx:advice>

2.SpringBoot整合Mybatis及多数据源配置

SpringBoot对各种常用软件的整合做了很多很好的封装,SpringBoot整合MyBatis网上有很多教程,这里只介绍一下多数据源的SpringBoot配置。

2.1 application.properties配置不同数据源的连接配置

java aop配置多数据源 设置自动重连逻辑_Mybatis_02

Mapper文件和Dao类同样根据数据源进行分组

java aop配置多数据源 设置自动重连逻辑_Mybatis_03

2.2 创建数据源配置类

不同数据源创建不同的配置类,如下

java aop配置多数据源 设置自动重连逻辑_Mybatis_04

配置类内容如下:

package com.xxxx.xxx.datasource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

/**
 * Created by on 17/7/17.
 */
@Configuration
@MapperScan(basePackages = "com.xxxx.xxx.dao.source", sqlSessionTemplateRef  = "fromSqlSessionTemplate")
@PropertySource("classpath:application.properties")
public class SourceDataSourceConfig {

    @Bean(name = "fromDataSource")
    @ConfigurationProperties(prefix = "jdbcFrom")
    @Primary
    public DataSource fromDataSource() {

        return DataSourceBuilder.create().build();
    }

    @Bean(name = "fromSqlSessionFactory")
    @Primary
    public SqlSessionFactory fromSqlSessionFactory(@Qualifier("fromDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/source/*Mapper.xml"));
        return bean.getObject();
    }

    @Bean(name = "fromTransactionManager")
    @Primary
    public DataSourceTransactionManager fromTransactionManager(@Qualifier("fromDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "fromSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate fromSqlSessionTemplate(@Qualifier("fromSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

第二个数据源的配置类同上,只是bean的名称要取不一样的。

SpringMVC和SpringBoot整合mybatis以及多数据源配置就讲解到这里,更多精彩文章敬请期待。