Mybatis-plus配置多數(shù)據(jù)源,連接多數(shù)據(jù)庫方式
前言
工作的時候,遇到了需要將一個數(shù)據(jù)庫的一些數(shù)據(jù)插入或更新到另一個數(shù)據(jù)庫。
一開始使用
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ù)據(jù)的插入和更新。
但是每次都要對著這一條sql語句進行修改,十分麻煩,就想著能否同時連接兩個數(shù)據(jù)庫進行業(yè)務(wù)處理。
業(yè)務(wù)邏輯
使用Mybatis實現(xiàn)
首先,如果你的項目用的是Mybatis,那么以下配置可以實現(xiàn)配置多數(shù)據(jù)源,連接多數(shù)據(jù)庫的作用。但是,如果你使用的是Mybatis-plus,本人建議使用Mybatis-plus實現(xiàn)更加簡單易操作。
1、在yml配置文件中配置多數(shù)據(jù)庫
例如:
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ù)據(jù)庫配置中的url改為jdbc-url,否則無法配置多數(shù)據(jù)源。
2、創(chuàng)建不同的mapper,用于不同的數(shù)據(jù)庫
3、編寫數(shù)據(jù)源的配置類
例如:
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ù)據(jù)庫db1的mapper的包 public class DataSource1Config { @Bean(name = "db1DataSource") @ConfigurationProperties(prefix = "spring.datasource.db1")//指向yml配置文件中的數(shù)據(jù)庫配置 @Primary //主庫加這個注解,修改優(yōu)先權(quán),表示發(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ù)據(jù)庫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); } }
整體結(jié)構(gòu):
至此,需要修改或查詢哪個數(shù)據(jù)庫,只需要在對應(yīng)的com///mapper/db包中創(chuàng)建對應(yīng)的mapper類或者編寫特定的sql語句即可。
使用Mybatis-plus實現(xiàn)
Mybatis-plus官網(wǎng)很清楚的告訴了我們?nèi)绾闻渲枚鄶?shù)據(jù)源。
1、引入dynamic-datasource-spring-boot-starter
<dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>${version}</version> </dependency>
2、配置數(shù)據(jù)源
spring: datasource: dynamic: primary: mysql1 #設(shè)置默認的數(shù)據(jù)源或者數(shù)據(jù)源組,默認值即為mysql1 strict: false #嚴格匹配數(shù)據(jù)源,默認false. true未匹配到指定數(shù)據(jù)源時拋異常,false使用默認數(shù)據(jù)源 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) # 內(nèi)置加密,使用請查看詳細文檔 username: ENC(xxxxx) password: ENC(xxxxx) driver-class-name: com.mysql.jdbc.Driver #......省略
3、使用 @DS 切換數(shù)據(jù)源
@DS 可以注解在方法上或類上,同時存在就近原則 方法上注解 優(yōu)先于 類上注解。
注解 | 結(jié)果 |
---|---|
沒有@DS | 默認數(shù)據(jù)源 |
@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ù)據(jù);方法B調(diào)用的是@DS(“mysql2”),是將數(shù)據(jù)插入到mysql2數(shù)據(jù)庫中,那么我想在方法B中調(diào)用方法A,實現(xiàn)mysql1中查詢的數(shù)據(jù)插入到mysql2中,能夠成功嗎?
答案是:不可以。
要想實現(xiàn)這個功能,我們可以使用多數(shù)據(jù)源的一個類,簡單來說是一個隊列,將需要使用到的數(shù)據(jù)源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è)務(wù)代碼 DynamicDataSourceContextHolder.poll();
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
java中FileOutputStream中文亂碼問題解決辦法
這篇文章主要介紹了java中FileOutputStream中文亂碼問題解決辦法的相關(guān)資料,需要的朋友可以參考下2017-04-04SpringMVC中常用參數(shù)校驗類注解使用示例教程
這篇文章主要介紹了SpringMVC中常用參數(shù)校驗類注解使用示例教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-03-03Spring?IOC容器基于XML外部屬性文件的Bean管理
這篇文章主要為大家介紹了Spring?IOC容器Bean管理XML外部屬性文件,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05JAVA中使用FTPClient實現(xiàn)文件上傳下載實例代碼
本文給大家介紹如何利用jakarta commons中的FTPClient(在commons-net包中)實現(xiàn)上傳下載文件。非常不錯具有參考借鑒價值,感興趣的朋友一起學習吧2016-06-06