javascript
Spring Boot2.x-10 基于Spring Boot 2.1.2 + Mybatis 2.0.0实现多数据源,支持事务
文章目錄
- 概述
- 思路
- 步驟
- Step1 多數(shù)據(jù)源配置文件applicaiton.yml
- Step2 初始化多個數(shù)據(jù)源
- Step3 配置多個數(shù)據(jù)源
- 驗證測試
- 支持事務(wù)
- Step1 配置類中通過@Bean初始化DataSourceTransactionManager
- Step2 如何使用呢? @Transactional(DataSources.DB1_TRANSACTION)
- Step3 驗證事務(wù)
- 順便說下 集成JdbcTemplate
- Step1 配置類中通過@Bean初始化每個數(shù)據(jù)庫實例對應(yīng)的JdbcTemplate
- Step2 如何使用呢? @Autowired @Qualifier(DataSources.DB1_JDBCTEMPLATE)
- Step3 驗證
- 代碼
概述
Spring Boot2.x-09 基于Spring Boot + Mybatis使用自定義注解實現(xiàn)數(shù)據(jù)庫切換 通過自定義注解實現(xiàn)了數(shù)據(jù)庫的切庫。多數(shù)據(jù)源的支持我們通過這篇博文來梳理。
單個數(shù)據(jù)源 見 Spring Boot2.x-07Spring Boot2.1.2整合Mybatis
思路
讓不同的數(shù)據(jù)源綁定不同的mybatis配置,再細化一點就是讓不同的數(shù)據(jù)源掃描不同的包,讓不同包下的mapper連接不同的數(shù)據(jù)源去處理業(yè)務(wù)邏輯。
多說一句,對于跨庫的多表操作,這種整合是支持不了的
步驟
我們基于 Spring Boot2.x-09 基于Spring Boot + Mybatis使用自定義注解實現(xiàn)數(shù)據(jù)庫切換 來改造下,讓其支持多數(shù)據(jù)源。
Step1 多數(shù)據(jù)源配置文件applicaiton.yml
自定義前綴,在標注了@Configuration的配置類中通過prefix 將數(shù)據(jù)源關(guān)聯(lián)起來。 這里的配置類為DatasourceConfig。
# datasource db1 前綴為自定義的datasource-db1 spring:datasource-db1:driver-class-name: com.mysql.cj.jdbc.Driver # JDBC連接Mysql6以上com.mysql.cj.jdbc.Driver (服務(wù)端為Mysql8)url: jdbc:mysql://localhost:3306/db1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=falseusername: rootpassword: root# datasource db2 前綴為自定義的datasource-db2datasource-db2: driver-class-name: com.mysql.cj.jdbc.Driver # JDBC連接Mysql6以上com.mysql.cj.jdbc.Driver (服務(wù)端為Mysql8)url: jdbc:mysql://localhost:3306/db2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=falseusername: rootpassword: root# mybatis mybatis_db1: # 映射文件的路徑 , 這個切換數(shù)據(jù)源的場景下不能配置 * 通配符,有多個 逗號隔開,繼續(xù)跟 classpath:mapper_db1/XXX# 在MybatisConfig.java#sqlSessionFactoryBean方法中通過sqlSessionFactoryBean設(shè)置classpath:mapper_db1/*.xml ,不然每次都要改這個地方,不好維護。# mapper-locations: classpath:mapper_db1/*.xml # 類型別名包配置,只能指定具體的包,多個配置可以使用英文逗號隔開# 也可以通過sqlSessionFactoryBean.setTypeAliasesPackage("com.artisan.domain.db1")type-aliases-package: com.artisan.domain.db1# Mybatis SQL語句控制臺打印configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl# mybatis mybatis_db2: # 映射文件的路徑 , 這個切換數(shù)據(jù)源的場景下不能配置 * 通配符,有多個 逗號隔開,繼續(xù)跟 classpath:mapper/XXX# 在MybatisDB2Config.java#sqlSessionFactoryBean方法中通過sqlSessionFactoryBean設(shè)置classpath:mapper_db2/*.xml ,不然每次都要改這個地方,不好維護。#mapper-locations: classpath:mapper_db2/*.xml # 類型別名包配置,只能指定具體的包,多個配置可以使用英文逗號隔開type-aliases-package: com.artisan.domain.db2# Mybatis SQL語句控制臺打印configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImplStep2 初始化多個數(shù)據(jù)源
這里同時也初始化了JdbcTemplate和事務(wù)管理,當(dāng)然了對這個例子是可選操作。 主要是不同DataSource的初始化
多個數(shù)據(jù)源,操作JdbcTemplate和Transaction,需要指定使用哪個數(shù)據(jù)源,否則Spring根據(jù)type找到多個bean,不知道注入哪個。 【使用@Primary或者@Qualifier都可以】
package com.artisan.config;import javax.sql.DataSource;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.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager;import com.alibaba.druid.pool.DruidDataSource;@Configuration public class DatasourceConfig {//destroy-method="close":當(dāng)數(shù)據(jù)庫連接不使用的時候,將該連接重新放到數(shù)據(jù)池中@Bean(name=DataSources.DB1,destroyMethod="close")@ConfigurationProperties(prefix = "spring.datasource-db1")public DataSource dataSourceDB1() {// 創(chuàng)建數(shù)據(jù)源return DataSourceBuilder.create().type(DruidDataSource.class).build();}@Bean(name=DataSources.DB2,destroyMethod="close")@ConfigurationProperties(prefix = "spring.datasource-db2")public DataSource dataSourceDB2() {// 創(chuàng)建數(shù)據(jù)源return DataSourceBuilder.create().type(DruidDataSource.class).build();}// 支持JdbcTemplate (可選)@Bean(DataSources.DB1_JDBCTEMPLATE)public JdbcTemplate db1JdbcTemplate(@Qualifier(DataSources.DB1) DataSource dataSource) {return new JdbcTemplate(dataSource);}@Bean(DataSources.DB2_JDBCTEMPLATE)public JdbcTemplate db2JdbcTemplate(@Qualifier(DataSources.DB2) DataSource dataSource) {return new JdbcTemplate(dataSource);}// 支持事務(wù)(可選)@Bean(DataSources.DB1_TRANSACTION)public DataSourceTransactionManager db1TransactionManager(@Qualifier(DataSources.DB1) DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Bean(DataSources.DB2_TRANSACTION)public DataSourceTransactionManager db2TransactionManager(@Qualifier(DataSources.DB2) DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}}Step3 配置多個數(shù)據(jù)源
1. 掃描包的路徑,不同的數(shù)據(jù)源掃描的包路徑不同
2. 通過@Qualifier指定注入的數(shù)據(jù)源
3. Mybatis如果使用xml方式,配置文件中有配置項,通過前綴加載對應(yīng)的配置項
MybatisDB1Config
package com.artisan.config;import javax.sql.DataSource;import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; 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.core.io.support.PathMatchingResourcePatternResolver;@Configuration // db1的接口類的包名 @MapperScan(basePackages = { "com.artisan.dao.db1" }, sqlSessionFactoryRef = "db1SqlSessionFactoryBean") public class MybatisDB1Config {@Autowired// 必須指定注入哪個數(shù)據(jù)源,否則找到多個會注入失敗@Qualifier(DataSources.DB1)private DataSource db1;@Bean(name = "db1SqlSessionFactoryBean")@ConfigurationProperties(prefix = "mybatis-db1") // 和 配置文件中的前綴保持一致// @Primary 如果SqlSessionFactoryBean的名字和MybatisDB2Config中的一致(默認方法名),需要加上這個注解,優(yōu)先注入該SqlSessionFactoryBean// 這里我們通過bean指定了name,并且方法名也不一樣,所以如果情況不一樣,看是否需要加入@Primary 。 如果需要兩個方法上加一個就行了,都加的話,spring又找不到bean注入啦。。public SqlSessionFactoryBean db1SqlSessionFactoryBean() throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();// 配置數(shù)據(jù)源sqlSessionFactoryBean.setDataSource(db1);// 如下的兩行代碼僅僅用于*.xml文件,如果整個持久層操作沒用到xml文件的話,比如使用注解的方式,則無需加// 解決配置到配置文件中通過*配置找不到mapper文件的問題。 如果不設(shè)置這一行,在配置文件中,只能使用數(shù)組的方式一個個的羅列出來,并且要指定具體的文件名sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper_db1/*.xml"));// 也可以通過在application.yml中配置//sqlSessionFactoryBean.setTypeAliasesPackage("com.artisan.domain.db1");return sqlSessionFactoryBean;}// 可選,如果需要通過SqlSessionTemplate來操作持久層就通過@Bean實例化,我們這個例子中沒用到,隨手寫出來了@Bean(name="db1SqlSessionTemplate")public SqlSessionTemplate db1SqlSessionTemplate() throws Exception {SqlSessionTemplate template = new SqlSessionTemplate(db1SqlSessionFactoryBean().getObject());return template;}}MybatisDB2Config
package com.artisan.config;import javax.sql.DataSource;import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver;@Configuration @MapperScan(basePackages = { "com.artisan.dao.db2" },sqlSessionFactoryRef="db2SqlSessionFactoryBean" ) // 掃描的mybatis接口類的包名 public class MybatisDB2Config {@Autowired// 必須指定注入哪個數(shù)據(jù)源,否則找到多個會注入失敗@Qualifier(DataSources.DB2)private DataSource db2;@Bean(name="db2SqlSessionFactoryBean")@ConfigurationProperties(prefix = "mybatis-db2") // 和 配置文件中的前綴保持一致public SqlSessionFactoryBean db2SqlSessionFactoryBean() throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();// 配置數(shù)據(jù)源sqlSessionFactoryBean.setDataSource(db2);// 解決配置到配置文件中通過*配置找不到mapper文件的問題。 如果不設(shè)置這一行,在配置文件中,只能使用數(shù)組的方式一個個的羅列出來,并且要指定具體的文件名sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper_db2/*.xml"));return sqlSessionFactoryBean;}// 可選,如果需要通過SqlSessionTemplate來操作持久層就通過@Bean實例化,我們這個例子中沒用到,隨手寫出來了@Bean(name = "db2SqlSessionTemplate")public SqlSessionTemplate db2SqlSessionTemplate() throws Exception {SqlSessionTemplate template = new SqlSessionTemplate(db2SqlSessionFactoryBean().getObject());return template;}}驗證測試
數(shù)據(jù)庫表、Domain , Dao , Service,Controller中的代碼見下面的Github連接,很簡單,就不貼了,只說重點
貼下數(shù)據(jù)庫的初始數(shù)據(jù)吧
db1:
db2:
啟動Spring Boot工程,
訪問 http://localhost:8080/db1?id=1
訪問 http://localhost:8080/db2?id=1
支持事務(wù)
Step1 配置類中通過@Bean初始化DataSourceTransactionManager
Step2 如何使用呢? @Transactional(DataSources.DB1_TRANSACTION)
Step3 驗證事務(wù)
訪問: http://localhost:8080/db1/transTest
數(shù)據(jù)庫中的數(shù)據(jù)
為了方便驗證 artisanMapper.updateArtisan(artisan)中故意寫錯了個字段名,讓其拋出異常,測試回滾。 執(zhí)行方法后,可以看到因為第二個方法報錯,第一個方法中的插入的數(shù)據(jù)也回滾了 。
順便說下 集成JdbcTemplate
持久層我們這里用的Mybatis,有些同學(xué)說我想用JdbcTemplate呢
Step1 配置類中通過@Bean初始化每個數(shù)據(jù)庫實例對應(yīng)的JdbcTemplate
Step2 如何使用呢? @Autowired @Qualifier(DataSources.DB1_JDBCTEMPLATE)
Step3 驗證
啟動工程,訪問 http://localhost:8080/db1/jdbcTemplateTest
查看數(shù)據(jù)
代碼
https://github.com/yangshangwei/MultiDataSource
總結(jié)
以上是生活随笔為你收集整理的Spring Boot2.x-10 基于Spring Boot 2.1.2 + Mybatis 2.0.0实现多数据源,支持事务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Boot2.x-09 基于
- 下一篇: Spring Boot2.x-11 使用