Spring Boot 入門系列(二十三)整合Mybatis,實現多資料來源配置!

章為忠發表於2021-09-02

d之前介紹了Spring Boot 整合mybatis 使用註解方式配置的方式實現增刪改查以及一些複雜自定義的sql 語句 。想必大家對spring boot 專案中,如何使用mybatis 有了一定的瞭解。但在很多業務場景下,我們需要在一個專案中配置多個資料來源來實現業務邏輯,例如:現有電商業務,商品和庫存資料分別放在不同的資料庫中,這就要求我們的系統架構支援同時配置多個資料來源實現相關業務操作。那麼Spring Boot 如何應對這種多資料來源的場景呢?其實,在 Spring Boot 專案中配置多資料來源十分便捷。接下來就聊一聊 Spring Boot 整合mybatis 實現多資料來源的相關配置。

關於整合mybatis 部分,之前已經介紹過,這裡直接講 Mybatis 多資料來源的配置的配置實現,不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/zhangweizhong/category/1657780.html

 

一、配置資料庫

首先在系統配置檔案中,需要配置多個資料來源,即在application.properties 檔案中增加如下配置:

# mybatis 多資料來源配置
# 資料庫1的配置
spring.datasource.test1.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.test1.jdbc-url = jdbc:mysql://localhost:3306/zwz_test?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.test1.username = root
spring.datasource.test1.password = root
# 資料庫2的配置
spring.datasource.test2.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.test2.jdbc-url = jdbc:mysql://localhost:3306/zwz_test2?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.test2.username = root
spring.datasource.test2.password = root

注意:

1、這裡配置的是兩個一樣的資料庫zwz_test 和zwz_test2。

 2、資料庫連線的配置使用jdbc-url , 不是之前的url ,這點需要注意。

 

二、資料來源配置類

1、主資料來源配置類

在config 包中,建立 DataSource1Config 類。此類配置主資料來源。

package com.weiz.config;

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.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.weiz.mapper.test1", sqlSessionFactoryRef = "test1SqlSessionFactory")
public class DataSource1Config {
        @Bean(name = "test1DataSource")
        @ConfigurationProperties(prefix = "spring.datasource.test1")
        @Primary
        public DataSource testDataSource() {
                return DataSourceBuilder.create().build();
        }

        @Bean(name = "test1SqlSessionFactory")
        @Primary
        public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource) throws Exception {
                SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
                bean.setDataSource(dataSource);
                return bean.getObject();
        }

        @Bean(name = "test1TransactionManager")
        @Primary
        public DataSourceTransactionManager testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) {
                return new DataSourceTransactionManager(dataSource);
        }

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

 

2、配置其他資料來源

在config 包中,建立DataSource2Config 類。此類配置其他普通資料來源。

package com.weiz.config;

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.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = "com.weiz.mapper.test2", sqlSessionFactoryRef = "test2SqlSessionFactory")
public class DataSource2Config {
        @Bean(name = "test2DataSource")
        @ConfigurationProperties(prefix = "spring.datasource.test2")
        public DataSource testDataSource() {
                return DataSourceBuilder.create().build();
        }

        @Bean(name = "test2SqlSessionFactory")
        public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource) throws Exception {
                SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
                bean.setDataSource(dataSource);
                return bean.getObject();
        }

        @Bean(name = "test2TransactionManager")
        public DataSourceTransactionManager testTransactionManager(@Qualifier("test2DataSource") DataSource dataSource) {
                return new DataSourceTransactionManager(dataSource);
        }

        @Bean(name = "test2SqlSessionTemplate")
        public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
                return new SqlSessionTemplate(sqlSessionFactory);
        }
}

說明, DataSource1Config 和  DataSource2Config 即是相關的主資料來源配置類和普通資料來源配置類。

com.weiz.mapper.test1 為 掃描的mapper的路徑。

可以看到兩個資料來源都配置的各自的DataSource、SqlSessionFactory、TransactionManager和SqlSessionTemplate 。

 

雖然兩個類看著差不多,但是需要特別注意以下幾點

  1、主資料來源配置需要加@Primary 註解,其他普通資料來源不能加這個註解,否則會報錯,複製的時候小心。

  2、各個資料來源配置的 basePackages 掃描路徑需要配置正確。配置錯了不會出異常,但是執行的時候,會找錯資料庫。

 

3、呼叫測試

首先,建立com.weiz.mapper.test1 和 com.weiz.mapper.test2 包,將之前的UserMapper ,重名命為User1Mapper 和User2Mapper 複製到相應的包中。

然後,UserServiceImpl 分別注入兩個不同的 Mapper,想操作哪個資料來源就使用哪個資料來源的 Mapper 進行操作處理。

package com.weiz.service.impl;

import com.weiz.mapper.test1.User1Mapper;
import com.weiz.mapper.test2.User2Mapper;
import com.weiz.pojo.User;
import com.weiz.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private User1Mapper user1Mapper;

    @Autowired
    private User2Mapper user2Mapper;

    @Override
    public int saveUser(User user) {
        user1Mapper.insert(user);
        return user2Mapper.insert(user);
    }

    @Override
    public int updateUser(User user) {
        user1Mapper.updateByPrimaryKey(user);
        return user2Mapper.updateByPrimaryKey(user);
    }

    @Override
    public int deleteUser(String userId) {
        user1Mapper.deleteByPrimaryKey(userId);
        return user2Mapper.deleteByPrimaryKey(userId);
    }

    @Override
    public User queryUserById(String userId) {
        user1Mapper.selectByPrimaryKey(userId);
        return user2Mapper.selectByPrimaryKey(userId);
    }
}

這裡是一個簡單的測試程式,實際專案中是根據實際的業務,呼叫不同的mapper 實現的,或者通過註解配置,動態切換資料來源。

 

三、測試

啟動專案,瀏覽器中輸入如下地址: http://localhost:8088/mybatis/saveuser ,可以看到兩個資料庫中,都增加了一條使用者資訊。

資料庫 zwz_test 中 使用者表sys_user 增加了一條記錄。

 

 

 

資料庫 zwz_test2 中 使用者表sys_user 也增加了一條同樣的記錄。

 

四、可能會遇到的坑

1、資料庫連線的配置使用jdbc-url , 不是之前的url 。這點需要注意。

2、主資料來源配置需要加@Primary 註解,其他普通資料來源不能加這個註解,否則會報錯,複製的時候小心。

3、各個資料來源配置的 basePackages 掃描路徑需要配置正確。配置錯了不會出異常,但是執行的時候,會找錯資料庫。

4、如果Mybatis使用的是xml 配置版,xml位置需要在每個config顯示置頂位置。

 

最後

以上,就把Spring Boot整合Mybatis,實現多資料來源配置的功能介紹完了。操作看似簡單,其實還是得小心仔細。不然很容易出錯。

此外配置多資料來源之後,還涉及到資料來源切換的問題,網上有很多種方法,比較流行的就是druid框架實現多資料來源切換。這個後面再講吧。

還有,這裡沒有使用事務,如果採用事務需要分別配置每個資料來源的事務,並採用事務性註解進行統一管理。這裡不細說大家自己研究吧。

這個系列課程的完整原始碼,也會提供給大家。大家關注我的微信公眾號(架構師精進),回覆:springboot原始碼。獲取這個系列課程的完整原始碼。

 

相關文章