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

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

關於整合mybatis 部分,之前已經介紹過,這裡直接講 Mybatis 多數據源的配置的配置實現,不清楚的朋友可以看看之前的文章://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 實現的,或者通過註解配置,動態切換數據源。

 

三、測試

啟動項目,瀏覽器中輸入如下地址: //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源碼。獲取這個系列課程的完整源碼。