springboot中mybatis多數據源動態切換實現
在開發中,動態數據源配置還是用的比較多的,比如在多數據源使用方面,又或者是在多個DB之間切換方面。這裡給出一個動態數據源的配置方案,兩個DB均以mysql為例。
多數據源配置引入
mybatis和mysql在springboot中的引入這裡就不在說瞭,不瞭解的可以參見springboot中mysql與mybatis的引入。
數據源配置如下:
datasource: master: type: com.alibaba.druid.pool.DruidDataSource jdbc-url: jdbc:mysql://127.0.0.1:3306/sbac_master?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true username: root password: 1234 driver-class-name: com.mysql.cj.jdbc.Driver log: type: com.alibaba.druid.pool.DruidDataSource jdbc-url: jdbc:mysql://127.0.0.1:3306/sbac_log?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true username: root password: 1234 driver-class-name: com.mysql.cj.jdbc.Driver
mybatis的配置引入如下:
mybatis: config-location: classpath:mybatis-config.xml mapper-locations: classpath:com/lazycece/sbac/mysql/data/dao/*/mapper/*.xml
這裡已然使用的是springboot的自動配置功能配置mybatis信息,隻是手動指定瞭數據源的。如下所示,指定瞭master和log兩個數據源,設置master為默認數據源:
@Configuration public class MultiDataSource { public static final String MASTER_DATA_SOURCE = "masterDataSource"; public static final String LOG_DATA_SOURCE = "logDataSource"; @Bean(name = MultiDataSource.MASTER_DATA_SOURCE) @ConfigurationProperties(prefix = "datasource.master") public DataSource masterDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = MultiDataSource.LOG_DATA_SOURCE) @ConfigurationProperties(prefix = "datasource.log") public DataSource logDataSource() { return DataSourceBuilder.create().build(); } @Primary @Bean(name = "dynamicDataSource") public DynamicDataSource dataSource() { DynamicDataSource dynamicDataSource = new DynamicDataSource(); dynamicDataSource.setDefaultTargetDataSource(masterDataSource()); Map<Object, Object> dataSourceMap = new HashMap<>(4); dataSourceMap.put(MASTER_DATA_SOURCE, masterDataSource()); dataSourceMap.put(LOG_DATA_SOURCE, logDataSource()); dynamicDataSource.setTargetDataSources(dataSourceMap); return dynamicDataSource; } }
動態數據源路由實現
引入瞭配置信息之後,便是該說如何實現多數據源切換瞭。我們是通過實現AbstractRoutingDataSource類的determineCurrentLookupKey方法來實現數據源的動態路由,設置ThreadLocal線程保護變量存儲數據源key,確保線程間不受影響。
package com.lazycece.sbac.mysql.multi.config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /** * @author lazycece */ public class DynamicDataSource extends AbstractRoutingDataSource { private static final Logger LOGGER = LoggerFactory.getLogger(DynamicDataSource.class); private static final ThreadLocal<String> DATA_SOURCE_KEY = new ThreadLocal<>(); static void changeDataSource(String dataSourceKey) { DATA_SOURCE_KEY.set(dataSourceKey); } static void clearDataSource() { DATA_SOURCE_KEY.remove(); } @Override protected Object determineCurrentLookupKey() { String key = DATA_SOURCE_KEY.get(); LOGGER.info("current data-source is {}", key); return key; } }
隨後,便是用AOP的方式來實現數據源的動態切換,註解和切面定義如下:
@Documented @Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.TYPE}) public @interface DataSource { String value(); } @Component @Aspect public class DataSourceConfig { @Before("@annotation(dataSource)") public void beforeSwitchDataSource(DataSource dataSource) { DynamicDataSource.changeDataSource(dataSource.value()); } @After("@annotation(DataSource)") public void afterSwitchDataSource() { DynamicDataSource.clearDataSource(); } }
動態數據源切換使用
動態數據源切換隻需要在業務中使用@DataSource註解來標明需要使用的數據源即可,如下所示(這裡隻貼出關鍵代碼):
@Service public class DynamicDataSourceServiceImpl implements DynamicDataSourceService { @Resource private UserDao userDao; @Resource private SystemLogDao systemLogDao; @Override @DataSource(value = MultiDataSource.MASTER_DATA_SOURCE) public void addUserInfo(User user) { userDao.insert(user); } @Override @DataSource(value = MultiDataSource.MASTER_DATA_SOURCE) public User getUserInfo(String username) { return userDao.findByUsername(username); } @Override @DataSource(value = MultiDataSource.LOG_DATA_SOURCE) public void addSystemLog(SystemLog systemLog) { systemLogDao.insert(systemLog); } @Override @DataSource(value = MultiDataSource.LOG_DATA_SOURCE) public List<SystemLog> getSystemLogInfo(Date beginTime, Date endTime) { return systemLogDao.findByCreateTime(beginTime, endTime); } }
案例源碼
案例源碼地址: https://github.com/lazycece/springboot-actual-combat/tree/master/springboot-ac-mysql/springboot-ac-mysql-multi
到此這篇關於springboot中mybatis多數據源動態切換實現的文章就介紹到這瞭,更多相關springboot mybatis多數據源動態切換內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Springboot動態切換數據源的具體實現與原理分析
- 基於 SpringBoot 實現 MySQL 讀寫分離的問題
- MyBatis-Plus 集成動態多數據源的實現示例
- SpringBoot項目中如何實現MySQL讀寫分離詳解
- springboot配置多數據源的一款框架(dynamic-datasource-spring-boot-starter)