11

//定义数据源枚举
public enum DataSourceKey {
master,
slave,
}

22

/**
* 数据源路由
*/
@Slf4j
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
log.error("Current DataSource is [{}]", DynamicDataSourceContextHolder.getDataSourceKey());
return DynamicDataSourceContextHolder.getDataSourceKey();
} }
/**
* 数据源路由holder
*/
@Slf4j
public class DynamicDataSourceContextHolder {
private static int counter = 0; private static final ThreadLocal<String> CONTEXT_HOLDER = ThreadLocal.withInitial(DataSourceKey.master::name); /**
* 所有数据源key
*/
public static List<Object> dataSourceKeys = new ArrayList<>(); /**
* 从数据源key
*/
public static List<Object> slaveDataSourceKeys = new ArrayList<>(); /**
*
* set数据源
*/
public static void setDataSourceKey(String key) {
CONTEXT_HOLDER.set(key);
} /**
* get数据源
*/
public static String getDataSourceKey() {
return CONTEXT_HOLDER.get();
}
/**
* 主数据源
*/
public static void useMasterDataSource() {
CONTEXT_HOLDER.set(DataSourceKey.master.name());
} /**
* 从数据源
*/
public static void useSlaveDataSource() {
try {
int datasourceKeyIndex = counter % slaveDataSourceKeys.size();//负载均衡-轮询
CONTEXT_HOLDER.set(String.valueOf(slaveDataSourceKeys.get(datasourceKeyIndex)));
counter++;
} catch (Exception e) {
log.error("Switch slave datasource failed, error message is {}", e.getMessage());
useMasterDataSource();
e.printStackTrace();
}
} public static void clearDataSourceKey() {
CONTEXT_HOLDER.remove();
} public static boolean containDataSourceKey(String key) {
return dataSourceKeys.contains(key);
} }

33

@Configuration
@MapperScan(basePackages = "com.buyi.mytransaction.dao.one", sqlSessionFactoryRef = "mybatisSqlSessionFactoryOne")
public class MyDynamicMybatisDataSource { @Bean(name = "master")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.one.master", ignoreInvalidFields = true)
public DataSource master() {
return new DruidDataSource();
} @Bean(name = "slave")
@ConfigurationProperties(prefix = "spring.datasource.one.slave", ignoreInvalidFields = true)
public DataSource slave() {
return new DruidDataSource();
} @Bean("dynamicDataSource")
public DataSource dynamicDataSource() {
DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();
Map<Object, Object> dataSourceMap = new HashMap<>(4);
dataSourceMap.put(DataSourceKey.master.name(), master());
dataSourceMap.put(DataSourceKey.slave.name(), slave()); dynamicRoutingDataSource.setDefaultTargetDataSource(master());//默认数据源
dynamicRoutingDataSource.setTargetDataSources(dataSourceMap);//数据源 DynamicDataSourceContextHolder.dataSourceKeys.addAll(dataSourceMap.keySet());//所有数据源
DynamicDataSourceContextHolder.slaveDataSourceKeys.addAll(dataSourceMap.keySet());//设置从数据源
DynamicDataSourceContextHolder.slaveDataSourceKeys.remove(DataSourceKey.master.name());
return dynamicRoutingDataSource;
} //事务管理器
@Bean(name = "mybatisTransactionManagerOne")
@Primary
public DataSourceTransactionManager mybatisTransactionManager(@Qualifier("dynamicDataSource") DataSource dataSource) throws Exception {
return new DataSourceTransactionManager(dataSource);
} //会话工厂
@Bean("mybatisSqlSessionFactoryOne")
@Primary
public SqlSessionFactory mybatisSqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sf = new SqlSessionFactoryBean();
sf.setDataSource(dataSource);
sf.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:repository/one/**/*Mapper.xml")); //自动转驼峰 resultType="***"
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
sf.setConfiguration(configuration);
return sf.getObject();
} }

44

@Slf4j
@Aspect
@Component
public class DynamicDataSourceAspect { private final String[] QUERY_PREFIX = {"select","query"}; @Pointcut("execution( * com.buyi.mytransaction.dao.one.*.*(..))")
public void daoAspect() {
} /**
* 切换数据源
*/
@Before("daoAspect()")
public void switchDataSource(JoinPoint point) {
Boolean isQueryMethod = isQueryMethod(point.getSignature().getName());
if (isQueryMethod) {
DynamicDataSourceContextHolder.useSlaveDataSource();
log.debug("Switch DataSource to [{}] in Method [{}]",
DynamicDataSourceContextHolder.getDataSourceKey(), point.getSignature());
}
} /**
* 重置数据源
*/
@After("daoAspect())")
public void restoreDataSource(JoinPoint point) {
DynamicDataSourceContextHolder.clearDataSourceKey();
log.debug("Restore DataSource to [{}] in Method [{}]",
DynamicDataSourceContextHolder.getDataSourceKey(), point.getSignature());
} private Boolean isQueryMethod(String methodName) {
for (String prefix : QUERY_PREFIX) {
if (methodName.startsWith(prefix)) {
return true;
}
}
return false;
}
}
    @Test
//测试切换数据源
public void test3() {
Company c = Company.builder().companyId("789").companyName("百度").memo("人工智能").build();
oneCompanyservice.oneInsert(c); List<Company> companyList = oneCompanyservice.selectAll();
for (Company company : companyList) {
System.out.println(company);
//Company(companyId=999, companyName=百度子公司, memo=111)
//此条数据在从数据库中已存在
}
}

Spring动态切换数据源的更多相关文章

  1. Spring动态切换数据源及事务

    前段时间花了几天来解决公司框架ssm上事务问题.如果不动态切换数据源话,直接使用spring的事务配置,是完全没有问题的.由于框架用于各个项目的快速搭建,少去配置各个数据源配置xml文件等.采用了动态 ...

  2. spring动态切换数据源(一)

    介绍下spring数据源连接的源码类:| 1 spring动态切换连接池需要类AbstractRoutingDataSource的源码 2 /* 3 * Copyright 2002-2017 the ...

  3. Spring AOP动态切换数据源

    现在稍微复杂一点的项目,一个数据库也可能搞不定,可能还涉及分布式事务什么的,不过由于现在我只是做一个接口集成的项目,所以分布式就先不用了,用Spring AOP来达到切换数据源,查询不同的数据库就可以 ...

  4. Spring + Mybatis 项目实现动态切换数据源

    项目背景:项目开发中数据库使用了读写分离,所有查询语句走从库,除此之外走主库. 最简单的办法其实就是建两个包,把之前数据源那一套配置copy一份,指向另外的包,但是这样扩展很有限,所有采用下面的办法. ...

  5. Spring+Mybatis动态切换数据源

    功能需求是公司要做一个大的运营平台: 1.运营平台有自身的数据库,维护用户.角色.菜单.部分以及权限等基本功能. 2.运营平台还需要提供其他不同服务(服务A,服务B)的后台运营,服务A.服务B的数据库 ...

  6. Spring动态切换多数据源事务开启后,动态数据源切换失效解决方案

    关于某操作中开启事务后,动态切换数据源机制失效的问题,暂时想到一个取巧的方法,在Spring声明式事务配置中,可对不改变数据库数据的方法采用不支持事务的配置,如下: 对单纯查询数据的操作设置为不支持事 ...

  7. Spring Boot 如何动态切换数据源

    本章是一个完整的 Spring Boot 动态数据源切换示例,例如主数据库使用 lionsea 从数据库 lionsea_slave1.lionsea_slave2.只需要在对应的代码上使用 Data ...

  8. 在使用 Spring Boot 和 MyBatis 动态切换数据源时遇到的问题以及解决方法

    相关项目地址:https://github.com/helloworlde/SpringBoot-DynamicDataSource 1. org.apache.ibatis.binding.Bind ...

  9. Spring学习总结(16)——Spring AOP实现执行数据库操作前根据业务来动态切换数据源

    深刻讨论为什么要读写分离? 为了服务器承载更多的用户?提升了网站的响应速度?分摊数据库服务器的压力?就是为了双机热备又不想浪费备份服务器?上面这些回答,我认为都不是错误的,但也都不是完全正确的.「读写 ...

随机推荐

  1. python--17个新手常见Python运行时错误

    当初学 Python 时,想要弄懂 Python 的错误信息的含义可能有点复杂.这里列出了常见的的一些让你程序 crash 的运行时错误. 1)忘记在 if , elif , else , for , ...

  2. Java读取文件的时候,如何让指针重新回到文件的开头

    今天在测试IO流的使用的时候发现在reader读取文件之后,再向文件添加内容,再继续读文件,打印出的结果只能读取追加的文件. 如何才能重新读取呢?试了mark和reset,似乎会报异常.记在这以后看是 ...

  3. Android数据传递的五种方法汇总

    Android开发中,在不同模块(如Activity)间经常会有各种各样的数据需要相互传递,我把常用的几种 方法都收集到了一起.它们各有利弊,有各自的应用场景. 我现在把它们集中到一个例子中展示,在例 ...

  4. bzoj1067降雨量

    True和False都好搞 Maybe的情况: 1.Y年和X年的降雨量已知,X年的降雨量不超过Y年的降雨量,从Y+1到X-1年中存在至少一年的降雨量未知,从Y+1到X-1年中已知的降雨量都小于X年的降 ...

  5. Java基础 之 System.getProperty()方法

    Java基础 之 System.getProperty()方法大全 public static void main(String[] args) { System.out.println(" ...

  6. 解决苹果手机Safari浏览器下 字体显示为 蓝色的 问题

    解决苹果手机 Safari浏览器下   字体显示为蓝色的 问题 近期测试同学测试,wap站上,底部文字在苹果8上面 ,使用 Safari浏览器打开,一直显示 蓝色字体 其他正常,寻找半天无解,最后 阳 ...

  7. 「LOJ#10050」「一本通 2.3 例 2」The XOR Largest Pair (Trie

    题目描述 在给定的 $N$ 个整数 $A_1,A_2,A_3...A_n$ 中选出两个进行异或运算,得到的结果最大是多少? 输入格式 第一行一个整数$N$. 第二行$N$个整数$A_i$. 输出格式 ...

  8. UILabel UiButton 文字下面加下划线

    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"直接进入" ...

  9. HDOJ1728(限制转弯的迷宫问题)

    用bfs进行深搜,求出每个可达点的最小转弯数 #include<cstdio> #include<cstring> #include<queue> using na ...

  10. Java类的生命周期(转)

    引言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前国内java方面的教材大多只是告 ...