Spring Boot 2.x 多數據源配置之 MyBatis 篇


場景假設:現有電商業務,商品和庫存分別放在不同的庫

配置數據庫連接

app:
  datasource:

    first:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1/product?useSSL=false
      username: root
      password: root
      configuration:
        maximum-pool-size: 10

    second:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1/stock?useSSL=false
      username: root
      password: root
      configuration:
        maximum-pool-size: 10

添加配置類

FirstConfig

@Configuration
@MapperScan(
        basePackages  = {"com.karonda.springboot2datasourcesmybatis.dao.first"},// 1. dao 層所在的包
        sqlSessionTemplateRef = "firstSqlSessionTemplate")
public class FirstConfig {

    @Bean
    @Primary
    public SqlSessionTemplate firstSqlSessionTemplate() throws Exception {
        return new SqlSessionTemplate(firstSqlSessionFactory());
    }

    @Bean
    @Primary
    public DataSourceTransactionManager firstTransactionManager(){
        return new DataSourceTransactionManager(firstDataSource());
    }

    @Bean
    @Primary
    public SqlSessionFactory firstSqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(firstDataSource());
        factoryBean.setMapperLocations(
                new PathMatchingResourcePatternResolver()
                        .getResources("classpath:mapper/first/*.xml")); // 2. xml 所在路徑
        return factoryBean.getObject();
    }

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource.first")
    public DataSourceProperties firstDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource.first.configuration")
    public DataSource firstDataSource() {
        return firstDataSourceProperties()
                .initializeDataSourceBuilder()
                .type(HikariDataSource.class) // 3. 可以顯示指定連接池,也可以不顯示指定;即此行代碼可以注釋掉
                .build();
    }

}

SecondConfig

@Configuration
@MapperScan(
        basePackages = {"com.karonda.springboot2datasourcesmybatis.dao.second"},
        sqlSessionTemplateRef = "secondSqlSessionTemplate")
public class SecondConfig {

    @Bean
    public SqlSessionTemplate secondSqlSessionTemplate() throws Exception {
        return new SqlSessionTemplate(secondSqlSessionFactory());
    }

    @Bean
    public DataSourceTransactionManager secondTransactionManager(){
        return new DataSourceTransactionManager(secondDataSource());
    }

    @Bean
    public SqlSessionFactory secondSqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(secondDataSource());
        factoryBean.setMapperLocations(
                new PathMatchingResourcePatternResolver()
                        .getResources("classpath:mapper/second/*.xml"));
        return factoryBean.getObject();
    }

    @Bean
    @ConfigurationProperties("app.datasource.second")
    public DataSourceProperties secondDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties("app.datasource.second.configuration")
    public DataSource secondDataSource() {
        return secondDataSourceProperties()
                .initializeDataSourceBuilder()
                .type(HikariDataSource.class)
                .build();
    }

}

dao

public interface ProductMapper {

    Product getOneById(int id);
}
public interface StockMapper {

    Stock getOneByProductId(int productId);
}

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.karonda.springboot2datasourcesmybatis.dao.first.ProductMapper">
  <resultMap id="BaseResultMap" type="com.karonda.springboot2datasourcesmybatis.entity.Product">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="name" jdbcType="VARCHAR" property="name" />
  </resultMap>
  <sql id="Base_Column_List">
    id, name
  </sql>
  <select id="getOneById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from product
    where id = #{id,jdbcType=INTEGER}
  </select>
</mapper>
<mapper namespace="com.karonda.springboot2datasourcesmybatis.dao.second.StockMapper">
  <resultMap id="BaseResultMap" type="com.karonda.springboot2datasourcesmybatis.entity.Stock">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="product_id" jdbcType="INTEGER" property="productId" />
    <result column="stock_count" jdbcType="INTEGER" property="stockCount" />
  </resultMap>
  <sql id="Base_Column_List">
    id, product_id, stock_count
  </sql>
  <select id="getOneByProductId" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from stock
    where product_id = #{productId,jdbcType=INTEGER}
  </select>
</mapper>

使用示例

@Component
public class Task {

    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private StockMapper stockMapper;

    @Scheduled(cron = "0/5 * * * * ? ")
    public void job(){

        final int productId = 1;
        Product product = productMapper.getOneById(productId);
        Stock stock = stockMapper.getOneByProductId(productId);

        System.out.println("產品名稱: " + product.getName() + ", 庫存: " + stock.getStockCount());
    }

}

注意事項

  1. 使用多數據源,其中一個配置類需要添加 @Primary 注解 (有且僅有一個配置類需要添加)
  2. 在配置類中需要同時配置 dao 層所在的包和 xml 所在的路徑

總結

與 JPA 使用多數據源配置基本相同,具體可對比上一篇文章 Spring Boot 2.x 多數據源配置之 JPA 篇

參考:

Spring Boot(七):Mybatis 多數據源最簡解決方案

完整代碼:GitHub

本人 C# 轉 Java 的 newbie, 如有錯誤或不足歡迎指正,謝謝


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM