Mybatis-plus配置多數(shù)據源,連接多數(shù)據庫方式
前言
工作的時候,遇到了需要將一個數(shù)據庫的一些數(shù)據插入或更新到另一個數(shù)據庫。
一開始使用
insert into TABLE (col1,col2) VALUES (val1,val2) ON DUPLICATE KEY update col1 = "val1";
(這句sql語句的意思是:將val1,val2值插入到TABLE表的col1和col2字段中,如果出現(xiàn)主鍵或唯一沖突,就進行更新,只將col1值更新為val1)進行數(shù)據的插入和更新。
但是每次都要對著這一條sql語句進行修改,十分麻煩,就想著能否同時連接兩個數(shù)據庫進行業(yè)務處理。
業(yè)務邏輯

使用Mybatis實現(xiàn)
首先,如果你的項目用的是Mybatis,那么以下配置可以實現(xiàn)配置多數(shù)據源,連接多數(shù)據庫的作用。但是,如果你使用的是Mybatis-plus,本人建議使用Mybatis-plus實現(xiàn)更加簡單易操作。
1、在yml配置文件中配置多數(shù)據庫
例如:
spring:
application:
name: CONNECTION
datasource:
db1:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC
username: root
password: 123456
type: com.alibaba.druid.pool.DruidDataSource
db2:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://11.11.11.11:3306/test?serverTimezone=UTC
username: root
password: 654321
type: com.alibaba.druid.pool.DruidDataSource
注意,將數(shù)據庫配置中的url改為jdbc-url,否則無法配置多數(shù)據源。
2、創(chuàng)建不同的mapper,用于不同的數(shù)據庫

3、編寫數(shù)據源的配置類
例如:
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.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.czf.connect.mapper.db1", sqlSessionTemplateRef = "db1SqlSessionTemplate")
//此處的basePackages指向的是你存放數(shù)據庫db1的mapper的包
public class DataSource1Config {
@Bean(name = "db1DataSource")
@ConfigurationProperties(prefix = "spring.datasource.db1")//指向yml配置文件中的數(shù)據庫配置
@Primary //主庫加這個注解,修改優(yōu)先權,表示發(fā)現(xiàn)相同類型bean,優(yōu)先使用該方法。
public DataSource dbDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "db1SqlSessionFactory")
@Primary
public SqlSessionFactory dbSqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*xml"));
//這個的getResources指向的是你的mapper.xml文件,相當于在yml中配置的mapper-locations,此處配置了yml中就不用配置,或者說不會讀取yml中的該配置。
return bean.getObject();
}
@Bean(name = "db1TransactionManager")
@Primary
public DataSourceTransactionManager dbTransactionManager(@Qualifier("db1DataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "db1SqlSessionTemplate")
@Primary
public SqlSessionTemplate dbSqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
數(shù)據庫db2的配置類:
@Configuration
@MapperScan(basePackages = "com.czf.connect.mapper.db2", sqlSessionTemplateRef = "db2SqlSessionTemplate")
public class DataSource2Config {
@Bean(name = "db2DataSource")
@ConfigurationProperties(prefix = "spring.datasource.db2")
public DataSource dbDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "db2SqlSessionFactory")
public SqlSessionFactory dbSqlSessionFactory(@Qualifier("db2DataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*xml"));
return bean.getObject();
}
@Bean(name = "db2TransactionManager")
public DataSourceTransactionManager dbTransactionManager(@Qualifier("db2DataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "db2SqlSessionTemplate")
public SqlSessionTemplate dbSqlSessionTemplate(@Qualifier("db2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
整體結構:

至此,需要修改或查詢哪個數(shù)據庫,只需要在對應的com///mapper/db包中創(chuàng)建對應的mapper類或者編寫特定的sql語句即可。
使用Mybatis-plus實現(xiàn)
Mybatis-plus官網很清楚的告訴了我們如何配置多數(shù)據源。
1、引入dynamic-datasource-spring-boot-starter
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>${version}</version>
</dependency>2、配置數(shù)據源
spring:
datasource:
dynamic:
primary: mysql1 #設置默認的數(shù)據源或者數(shù)據源組,默認值即為mysql1
strict: false #嚴格匹配數(shù)據源,默認false. true未匹配到指定數(shù)據源時拋異常,false使用默認數(shù)據源
datasource:
mysql1:
url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver # 3.2.0開始支持SPI可省略此配置
mysql2:
url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
mysql2:
url: ENC(xxxxx) # 內置加密,使用請查看詳細文檔
username: ENC(xxxxx)
password: ENC(xxxxx)
driver-class-name: com.mysql.jdbc.Driver
#......省略
3、使用 @DS 切換數(shù)據源
@DS 可以注解在方法上或類上,同時存在就近原則 方法上注解 優(yōu)先于 類上注解。
| 注解 | 結果 |
|---|---|
| 沒有@DS | 默認數(shù)據源 |
| @DS(“dsName”) | dsName可以為組名也可以為具體某個庫的名稱 |
@Service
@DS("mysql1")
public class UserServiceImpl implements UserService {
@Autowired
private JdbcTemplate jdbcTemplate;
public List selectAll() {
return jdbcTemplate.queryForList("select * from user");
}
@Override
@DS("mysql2")
public List selectByCondition() {
return jdbcTemplate.queryForList("select * from user where age >10");
}
}
在這里會有個小問題,假如我編寫了兩個方法,方法A使用的是 @DS(“mysql1”) ,功能是查詢mysql1中的數(shù)據;方法B調用的是@DS(“mysql2”),是將數(shù)據插入到mysql2數(shù)據庫中,那么我想在方法B中調用方法A,實現(xiàn)mysql1中查詢的數(shù)據插入到mysql2中,能夠成功嗎?
答案是:不可以。
要想實現(xiàn)這個功能,我們可以使用多數(shù)據源的一個類,簡單來說是一個隊列,將需要使用到的數(shù)據源push進行,不用時再poll掉。就不用使用@DS注解了。
比如:
@RequestMapping("/Bmetohd")
public int Bmethod(){
DynamicDataSourceContextHolder.push("mysql1");
List<User> users = Amethod();
DynamicDataSourceContextHolder.poll();
DynamicDataSourceContextHolder.push("mysql2");
int num = 0;
for(User user: users){
int i = User2Mapper.insert(user);
num += i;
}
DynamicDataSourceContextHolder.poll();
return num;
}
重點:
DynamicDataSourceContextHolder.push("mysql1");
//業(yè)務代碼
DynamicDataSourceContextHolder.poll();
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
java項目實現(xiàn)統(tǒng)一打印入參出參等日志
這篇文章主要介紹了java項目實現(xiàn)統(tǒng)一打印入參出參等日志方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03
SpringSecurity頁面授權與登錄驗證實現(xiàn)(內存取值與數(shù)據庫取值)
Spring Security是一個能夠為基于Spring的企業(yè)應用系統(tǒng)提供聲明式的安全訪問控制解決方案的安全框架,本文主要介紹了SpringSecurity頁面授權與登錄驗證實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-06-06
Java結構型設計模式之組合模式Composite Pattern詳解
組合模式,又叫部分整體模式,它創(chuàng)建了對象組的數(shù)據結構組合模式使得用戶對單個對象和組合對象的訪問具有一致性。本文將通過示例為大家詳細介紹一下組合模式,需要的可以參考一下2022-11-11

