springboot中mybatis多数据源动态切换实现

网友投稿 589 2022-12-25

springboot中mybatis多数据源动态切换实现

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 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 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.inhttp://fo("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 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

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:智能车载终端经济(智能网联车载终端)
下一篇:智能车载终端解锁方案(智能解锁汽车高配功能)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~