基於SpirngBoot2.0+ 的 SpringBoot+Mybatis 多資料來源配置

Guide哥發表於2018-12-05

Github 地址:github.com/Snailclimb/…(SpringBoot和其他常用技術的整合,可能是你遇到的講解最詳細的學習案例,力爭新手也能看懂並且能夠在看完之後獨立實踐。基於最新的 SpringBoot2.0+,是你學習SpringBoot 的最佳指南。) ,歡迎各位 Star。

在上一篇文章《優雅整合 SpringBoot+Mybatis ,可能是你見過最詳細的一篇》中,帶著大家整合了 SpringBoot 和 Mybatis ,我們在當時使用的時單資料來源的情況,這種情況下 Spring Boot的配置非常簡單,只需要在 application.properties 檔案中配置資料庫的相關連線引數即可。但是往往隨著業務量發展,我們通常會進行資料庫拆分或是引入其他資料庫,從而我們需要配置多個資料來源。下面基於 SpringBoot+Mybatis ,帶著大家看一下 SpringBoot 中如何配置多資料來源。

這篇文章所涉及的程式碼其實是基於上一篇文章《優雅整合 SpringBoot+Mybatis ,可能是你見過最詳細的一篇》 的專案寫的,但是為了考慮部分讀者沒有讀過上一篇文章,所以我還是會一步一步帶大家走完每一步,力爭新手也能在看完之後獨立實踐。

一 開發前的準備

1.1 環境引數

  • 開發工具:IDEA
  • 基礎工具:Maven+JDK8
  • 所用技術:SpringBoot+Mybatis
  • 資料庫:MySQL
  • SpringBoot版本:2.1.0. SpringBoot2.0之後會有一些小坑,這篇文章會給你介紹到。注意版本不一致導致的一些小問題。

1.2 建立工程

建立一個基本的 SpringBoot 專案,我這裡就不多說這方面問題了,具體可以參考下面這篇文章:

blog.csdn.net/qq_34337272…

本專案結構:

基於SpirngBoot2.0+ 的 SpringBoot+Mybatis 多資料來源配置專案結構

1.3 建立兩個資料庫和 user 使用者表、money工資詳情表

我們一共建立的兩個資料庫,然後分別在這兩個資料庫中建立了 user 使用者表、money工資詳情表。

我們的使用者表很簡單,只有 4 個欄位:使用者 id、姓名、年齡、餘額。如下圖所示:

使用者表資訊

新增了“餘額money”欄位是為了給大家簡單的演示一下事務管理的方式。

我們的工資詳情表也很簡單,也只有 4 個欄位: id、基本工資、獎金和懲罰金。如下圖所示:

工資詳情表資訊

建表語句:

使用者表:

CREATE TABLE `user` (
  `id` int(13) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `name` varchar(33) DEFAULT NULL COMMENT '姓名',
  `age` int(3) DEFAULT NULL COMMENT '年齡',
  `money` double DEFAULT NULL COMMENT '賬戶餘額',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
複製程式碼

工資詳情表:

CREATE TABLE `money` (
  `id` int(33) NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `basic` int(33) DEFAULT NULL COMMENT '基本工資',
  `reward` int(33) DEFAULT NULL COMMENT '獎金',
  `punishment` int(33) DEFAULT NULL COMMENT '懲罰金',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
複製程式碼

1.4 配置 pom 檔案中的相關依賴

由於要整合 springboot 和 mybatis 所以加入了artifactId 為 mybatis-spring-boot-starter 的依賴,由於使用了Mysql 資料庫 所以加入了artifactId 為 mysql-connector-java 的依賴。

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
複製程式碼

1.5 配置 application.properties

配置兩個資料來源:資料庫1和資料庫2!

注意事項:

在1.0 配置資料來源的過程中主要是寫成:spring.datasource.url 和spring.datasource.driverClassName。 而在2.0升級之後需要變更成:spring.datasource.jdbc-url和spring.datasource.driver-class-name!不然在連線資料庫時可能會報下面的錯誤:

### Error querying database.  Cause: java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.
複製程式碼

另外在在2.0.2+版本後需要在datasource後面加上hikari,如果你沒有加的話,同樣可能會報錯。

server.port=8335
# 配置第一個資料來源
spring.datasource.hikari.db1.jdbc-url=jdbc:mysql://127.0.0.1:3306/erp?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8
spring.datasource.hikari.db1.username=root
spring.datasource.hikari.db1.password=153963
spring.datasource.hikari.db1.driver-class-name=com.mysql.cj.jdbc.Driver
# 配置第二個資料來源
spring.datasource.hikari.db2.jdbc-url=jdbc:mysql://127.0.0.1:3306/erp2?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8
spring.datasource.hikari.db2.username=root
spring.datasource.hikari.db2.password=153963
spring.datasource.hikari.db2.driver-class-name=com.mysql.cj.jdbc.Driver
複製程式碼

1.6 建立使用者類 Bean和工資詳情類 Bean

User.java

public class User {
    private int id;
    private String name;
    private int age;
    private double money;
    ...
    此處省略getter、setter以及 toString方法
}
複製程式碼

Money.java

public class Money {
    private int basic;
    private int reward;
    private int punishment;
    ...
    此處省略getter、setter以及 toString方法
}
複製程式碼

二 資料來源配置

通過 Java 類來實現對兩個資料來源的配置,這一部分是最關鍵的部分了,這裡主要提一下下面這幾點:

  • @MapperScan 註解中我們宣告瞭使用資料庫1的dao類所在的位置,還宣告瞭 SqlSessionTemplate 。SqlSessionTemplate是MyBatis-Spring的核心。這個類負責管理MyBatis的SqlSession,呼叫MyBatis的SQL方法,翻譯異常。SqlSessionTemplate是執行緒安全的,可以被多個DAO所共享使用。
  • 由於我使用的是全註解的方式開發,所以下面這條找並且解析 mapper.xml 配置語句被我註釋掉了 bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/db2/*.xml"));
  • 比如我們要宣告使用資料1,直接在 dao 層的類上加上這樣一個註釋即可:@Qualifier("db1SqlSessionTemplate")
  • 我們在資料庫1配置類的每個方法前加上了 @Primary 註解來宣告這個資料庫時預設資料庫,不然可能會報錯。

DataSource1Config.java

@Configuration
@MapperScan(basePackages = "top.snailclimb.db1.dao", sqlSessionTemplateRef = "db1SqlSessionTemplate")
public class DataSource1Config {

    /**
     * 生成資料來源.  @Primary 註解宣告為預設資料來源
     */
    @Bean(name = "db1DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.hikari.db1")
    @Primary
    public DataSource testDataSource() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 建立 SqlSessionFactory
     */
    @Bean(name = "db1SqlSessionFactory")
    @Primary
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        //  bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/db1/*.xml"));
        return bean.getObject();
    }

    /**
     * 配置事務管理
     */
    @Bean(name = "db1TransactionManager")
    @Primary
    public DataSourceTransactionManager testTransactionManager(@Qualifier("db1DataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

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

}

複製程式碼

DataSource2Config.java

@Configuration
@MapperScan(basePackages = "top.snailclimb.db2.dao", sqlSessionTemplateRef = "db2SqlSessionTemplate")
public class DataSource2Config {

    @Bean(name = "db2DataSource")
    @ConfigurationProperties(prefix = "spring.datasource.hikari.db2")
    public DataSource testDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "db2SqlSessionFactory")
    public SqlSessionFactory testSqlSessionFactory(@Qualifier("db2DataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        //bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/db2/*.xml"));
        return bean.getObject();
    }

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

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

}
複製程式碼

三 Dao 層開發和 Service 層開發

新建兩個不同的包存放兩個不同資料庫的 dao 和 service。

基於SpirngBoot2.0+ 的 SpringBoot+Mybatis 多資料來源配置

3.1 Dao 層

對於兩個資料庫,我們只是簡單的測試一個查詢這個操作。在上一篇文章《優雅整合 SpringBoot+Mybatis ,可能是你見過最詳細的一篇》中,我帶著大家使用註解實現了資料庫基本的增刪改查操作。

UserDao.java

@Qualifier("db1SqlSessionTemplate")
public interface UserDao {
    /**
     * 通過名字查詢使用者資訊
     */
    @Select("SELECT * FROM user WHERE name = #{name}")
    User findUserByName(String name);

}
複製程式碼

MoneyDao.java


@Qualifier("db2SqlSessionTemplate")
public interface MoneyDao {

    /**
     * 通過id 檢視工資詳情
     */
    @Select("SELECT * FROM money WHERE id = #{id}")
    Money findMoneyById(@Param("id") int id);
}

複製程式碼

3.2 Service 層

Service 層很簡單,沒有複雜的業務邏輯。

UserService.java

@Service
public class UserService {
    @Autowired
    private UserDao userDao;

    /**
     * 根據名字查詢使用者
     */
    public User selectUserByName(String name) {
        return userDao.findUserByName(name);
    }

}
複製程式碼

MoneyService.java

@Service
public class MoneyService {
    @Autowired
    private MoneyDao moneyDao;

    /**
     * 根據名字查詢使用者
     */
    public Money selectMoneyById(int id) {
        return moneyDao.findMoneyById(id);
    }

}

複製程式碼

四 Controller層

Controller 層也非常簡單。

UserController.java

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping("/query")
    public User testQuery() {
        return userService.selectUserByName("Daisy");
    }
}
複製程式碼

MoneyController.java

@RestController
@RequestMapping("/money")
public class MoneyController {
    @Autowired
    private MoneyService moneyService;

    @RequestMapping("/query")
    public Money testQuery() {
        return moneyService.selectMoneyById(1);
    }
}
複製程式碼

五 啟動類

//此註解表示SpringBoot啟動類
@SpringBootApplication
public class MainApplication {

    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }

}
複製程式碼

這樣基於SpirngBoot2.0+ 的 SpringBoot+Mybatis 多資料來源配置就已經完成了, 兩個資料庫都可以被訪問了。

相關文章