mysql多数据源切换_spring+mybatis多数据源动态切换

spring mvc+mybatis+多数据源切换 选取oracle,mysql作为例子切换数据源。oracle为默认数据源,在测试的action中,进行mysql和oracle的动态切换。

web.xml

webAppRootKey

trac

org.springframework.web.util.Log4jConfigListener

CharacterEncodingFilter

org.springframework.web.filter.CharacterEncodingFilter

encoding

utf8

forceEncoding

true

CharacterEncodingFilter

/*

dispatcher

org.springframework.web.servlet.DispatcherServlet

contextConfigLocation

/WEB-INF/dispatcher.xml

1

dispatcher

*.action

org.springframework.web.context.ContextLoaderListener

applicationContext.xml

配置 parentDataSource 的父bean.再配置多个数据源继承这个父bean,对driverClass,url,username,password,等数据源连接参数进行各自的重写。例如 mySqlDataSource ,在 DataSources bean中注入所有要切换的数据源,并且设置默认的数据源。

DataSourceInstances.java

public class DataSourceInstances{

public static final String MYSQL="MYSQL";

public static final String ORACLE="ORACLE";

}

DataSourceSwitch.java

public class DataSourceSwitch{

private static final ThreadLocal contextHolder=new ThreadLocal();

public static void setDataSourceType(String dataSourceType){

contextHolder.set(dataSourceType);

}

public static String getDataSourceType(){

return (String) contextHolder.get();

}

public static void clearDataSourceType(){

contextHolder.remove();

}

}

DataSources.java

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DataSources extends AbstractRoutingDataSource{

@Override

protected Object determineCurrentLookupKey() {

return DataSourceSwitch.getDataSourceType();

}

}

测试

@Controller

@SuppressWarnings("unused")

public class TestAction {

@Autowired

TestMapper testMapper;

@RequestMapping("/test.action")

public ModelAndView test(

HttpServletRequest request,

HttpServletResponse resp){

ModelAndView model = new ModelAndView("test");

model.addObject("test1", "这是一个测试,获取默认数据连接MYSQL:"+testMapper.test());

DataSourceSwitch.setDataSourceType(DataSourceInstances.ORACLE);

model.addObject("test2", "这是一个测试,获取数据连接ORACLE:"+testMapper.test());

DataSourceSwitch.setDataSourceType(DataSourceInstances.MYSQL);

model.addObject("test3", "这是一个测试,获取数据连接MYSQL:"+testMapper.test());

return model;

}

}

代码解释:

查看AbstractRoutingDataSource中的获取数据库连接源码

publicConnection getConnection()throwsSQLException

{returndetermineTargetDataSource().getConnection();

}

查看determineTargetDataSource方法

protected DataSource determineTargetDataSource()

{

Assert.notNull(resolvedDataSources, "DataSource router not initialized");

Object lookupKey = determineCurrentLookupKey();

DataSource dataSource = (DataSource)resolvedDataSources.get(lookupKey);

if(dataSource == null && (lenientFallback || lookupKey == null))

dataSource = resolvedDefaultDataSource;

if(dataSource == null)

throw new IllegalStateException((new StringBuilder()).append("Cannot determine target DataSource for lookup key [").append(lookupKey).append("]").toString());

else

return dataSource;

}

其中DataSource dataSource = (DataSource)resolvedDataSources.get(lookupKey); 中的resolvedDataSources 就是我们spring中设置的targetDataSources,是一个Map类型,里面有我们设置的MYSQL和ORACLE数据库连接池

注意determineCurrentLookupKey方法,

protected abstract Object determineCurrentLookupKey();

是一个抽象方法,需要我们去实现,我们将数据源对应的KEY放在本地线程中,那么可以随时在代码中进行切换数据源

默认数据源

在spring配置文件中,我们将defaultTargetDataSource注入到AbstractRoutingDataSource中

public voidafterPropertiesSet()

{if(targetDataSources == null)throw new IllegalArgumentException("Property 'targetDataSources' is required");

resolvedDataSources= newHashMap(targetDataSources.size());

Object lookupKey;

DataSource dataSource;for(Iterator iterator =targetDataSources.entrySet().iterator(); iterator.hasNext(); resolvedDataSources.put(lookupKey, dataSource))

{

java.util.Map.Entry entry=(java.util.Map.Entry)iterator.next();

lookupKey=resolveSpecifiedLookupKey(entry.getKey());

dataSource=resolveSpecifiedDataSource(entry.getValue());

}if(defaultTargetDataSource != null)

resolvedDefaultDataSource=resolveSpecifiedDataSource(defaultTargetDataSource);

}

AbstractRoutingDataSource类实现了InitializingBean接口,项目启动会实现方法afterPropertiesSet,生成resolvedDefaultDataSource实例,这样在determineTargetDataSource方法中如果获取本地线程变量中的连接位空,那么就选择默认数据源。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot项目中使用MyBatis Plus和Druid多数据的步骤如下: 1. 添加依赖 在`pom.xml`文件中添加以下依赖: ```xml <!-- MyBatis Plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.3.1</version> </dependency> <!-- Druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.6</version> </dependency> ``` 2. 配置Druid数据 在`application.yml`中添加Druid数据的配置: ```yaml spring: datasource: # 主数据 druid: url: jdbc:mysql://localhost:3306/main_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver # Druid配置 initialSize: 5 minIdle: 5 maxActive: 20 testOnBorrow: false testOnReturn: false testWhileIdle: true timeBetweenEvictionRunsMillis: 60000 validationQuery: SELECT 1 FROM DUAL # 从数据 druid2: url: jdbc:mysql://localhost:3306/sub_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver # Druid配置 initialSize: 5 minIdle: 5 maxActive: 20 testOnBorrow: false testOnReturn: false testWhileIdle: true timeBetweenEvictionRunsMillis: 60000 validationQuery: SELECT 1 FROM DUAL ``` 3. 配置MyBatis Plus 在`application.yml`中添加MyBatis Plus的配置: ```yaml mybatis-plus: # 主数据配置 mapper-locations: classpath:mapper/main/*.xml type-aliases-package: com.example.main.entity global-config: db-config: id-type: auto field-strategy: not_empty logic-delete-value: 1 logic-not-delete-value: 0 configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 从数据配置 multi-datasource: main: mapper-locations: classpath:mapper/main/*.xml type-aliases-package: com.example.main.entity sub: mapper-locations: classpath:mapper/sub/*.xml type-aliases-package: com.example.sub.entity ``` 4. 配置数据路由 在`com.example.config`包下创建`DynamicDataSourceConfig`类,用于配置数据路由: ```java @Configuration public class DynamicDataSourceConfig { @Bean @ConfigurationProperties("spring.datasource.druid") public DataSource mainDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean @ConfigurationProperties("spring.datasource.druid2") public DataSource subDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean public DataSource dynamicDataSource() { DynamicDataSource dynamicDataSource = new DynamicDataSource(); Map<Object, Object> dataSourceMap = new HashMap<>(2); dataSourceMap.put("main", mainDataSource()); dataSourceMap.put("sub", subDataSource()); // 将主数据作为默认数据 dynamicDataSource.setDefaultTargetDataSource(mainDataSource()); dynamicDataSource.setTargetDataSources(dataSourceMap); return dynamicDataSource; } @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dynamicDataSource()); sqlSessionFactoryBean.setTypeAliasesPackage("com.example.main.entity"); sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/main/*.xml")); return sqlSessionFactoryBean.getObject(); } @Bean public SqlSessionTemplate sqlSessionTemplate() throws Exception { return new SqlSessionTemplate(sqlSessionFactory()); } } ``` 5. 配置数据切换 在`com.example.config`包下创建`DynamicDataSource`类,用于实现数据切换: ```java public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSource(); } } ``` 在`com.example.config`包下创建`DataSourceContextHolder`类,用于存储当前数据: ```java public class DataSourceContextHolder { private static final ThreadLocal<String> DATASOURCE_CONTEXT_HOLDER = new ThreadLocal<>(); public static void setDataSource(String dataSource) { DATASOURCE_CONTEXT_HOLDER.set(dataSource); } public static String getDataSource() { return DATASOURCE_CONTEXT_HOLDER.get(); } public static void clearDataSource() { DATASOURCE_CONTEXT_HOLDER.remove(); } } ``` 在`com.example.aop`包下创建`DataSourceAspect`类,用于切换数据: ```java @Aspect @Component public class DataSourceAspect { @Pointcut("@annotation(com.example.annotation.DataSource)") public void dataSourcePointCut() { } @Before("dataSourcePointCut()") public void before(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); DataSource dataSource = signature.getMethod().getAnnotation(DataSource.class); if (dataSource != null) { String value = dataSource.value(); DataSourceContextHolder.setDataSource(value); } } @After("dataSourcePointCut()") public void after(JoinPoint joinPoint) { DataSourceContextHolder.clearDataSource(); } } ``` 6. 使用多数据 在需要使用从数据的方法上加上`@DataSource("sub")`注解,如: ```java @Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public List<User> listUsers() { DataSourceContextHolder.setDataSource("sub"); List<User> users = userMapper.selectList(null); DataSourceContextHolder.clearDataSource(); return users; } } ``` 这样就完成了Spring Boot项目中使用MyBatis Plus和Druid多数据的配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值