2019独角兽企业重金招聘Python工程师标准>>>

DatasourceConfig

package com.tonytaotao.dtsc.common.configuration.datasouce.normal; import com.alibaba.druid.pool.DruidDataSource;
import com.tonytaotao.dtsc.common.configuration.datasouce.DBTypeEnum;
import com.tonytaotao.dtsc.common.configuration.datasouce.DynamicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map; @Configuration
public class DatasourceConfig { /*------------------------------------------------- 普通多数据源----------------------------------------------*/ @Bean("multipleDataSource") @Primary public DataSource multipleDataSource() { DynamicDataSource dynamicDataSource = new DynamicDataSource(); Map< Object, Object > targetDataSources = new HashMap<>(); targetDataSources.put(DBTypeEnum.ONE.getCode(), createDataSourceOne()); targetDataSources.put(DBTypeEnum.TWO.getCode(), createDataSourceTwo()); dynamicDataSource.setTargetDataSources(targetDataSources); dynamicDataSource.setDefaultTargetDataSource(createDataSourceOne()); return dynamicDataSource; } private DataSource createDataSourceOne() { DruidDataSource druidDataSource = createDataSourceBase(); druidDataSource.setUrl("jdbc:mysql://localhost:3306/dtsc?useSSL=false&useUnicode=true&allowPublicKeyRetrieval=true&characterEncoding=UTF8&serverTimezone=GMT"); druidDataSource.setUsername("root"); druidDataSource.setPassword("123456"); return druidDataSource; } private DataSource createDataSourceTwo() { DruidDataSource druidDataSource = createDataSourceBase(); druidDataSource.setUrl("jdbc:mysql://localhost:3306/dtsc_1?useSSL=false&useUnicode=true&allowPublicKeyRetrieval=true&characterEncoding=UTF8&serverTimezone=GMT"); druidDataSource.setUsername("root"); druidDataSource.setPassword("123456"); return druidDataSource; } private DruidDataSource createDataSourceBase() { DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); druidDataSource.setInitialSize(50); druidDataSource.setMaxActive(100); druidDataSource.setMinIdle(5); druidDataSource.setMaxWait(1000); druidDataSource.setPoolPreparedStatements(false); druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(-1); druidDataSource.setValidationQuery("SELECT 1"); druidDataSource.setValidationQueryTimeout(1); druidDataSource.setTestOnBorrow(false); druidDataSource.setTestOnReturn(false); druidDataSource.setTestWhileIdle(true); druidDataSource.setTimeBetweenEvictionRunsMillis(60000); druidDataSource.setMinEvictableIdleTimeMillis(30000); return druidDataSource; } }

MybatisPlusConfig

package com.tonytaotao.dtsc.common.configuration.datasouce.normal; import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
import java.io.IOException; @Configuration
@MapperScan({"com.tonytaotao.dtsc.*.mapper"})
public class MybatisPlusConfig { /** * 性能分析插件 * @return */ @Bean @Profile({"dev","sit"}) public PerformanceInterceptor performanceInterceptor() { return new PerformanceInterceptor(); } /** * 分页插件 * @return */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } /** * * @return */ @Bean("sqlSessionFactory") public MybatisSqlSessionFactoryBean sqlSessionFactory(@Qualifier("multipleDataSource") DataSource multipleDataSource) { try { MybatisSqlSessionFactoryBean sqlSessionFactoryBean = mybatisSqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(multipleDataSource); return sqlSessionFactoryBean; } catch (IOException e) { e.printStackTrace(); return null; } } private MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean() throws IOException{ MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); mybatisSqlSessionFactoryBean.setGlobalConfig(globalConfig()); mybatisSqlSessionFactoryBean.setConfiguration(mybatisConfiguration()); mybatisSqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:com/tonytaotao/dtsc/*/mapper/xml/*Mapper.xml")); mybatisSqlSessionFactoryBean.setTypeAliasesPackage("com.tonytaotao.dtsc.*.entity"); return mybatisSqlSessionFactoryBean; } private GlobalConfig globalConfig() { GlobalConfig globalConfig = new GlobalConfig(); GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig(); dbConfig.setIdType(IdType.AUTO); dbConfig.setDbType(DbType.MYSQL); dbConfig.setFieldStrategy(FieldStrategy.NOT_EMPTY); dbConfig.setTableUnderline(true); dbConfig.setLogicDeleteValue("0"); dbConfig.setLogicNotDeleteValue("1"); globalConfig.setDbConfig(dbConfig); LogicSqlInjector logicSqlInjector = new LogicSqlInjector(); globalConfig.setSqlInjector(logicSqlInjector); return globalConfig; } private MybatisConfiguration mybatisConfiguration() { MybatisConfiguration mybatisConfiguration = new MybatisConfiguration(); // 源码里面如果有configuration, 不会注入BaseMapper 里面的方法, 所以这里要这样写 mybatisConfiguration.init(globalConfig()); mybatisConfiguration.setMapUnderscoreToCamelCase(true); mybatisConfiguration.setCacheEnabled(false); return mybatisConfiguration; } }

TransationConfig

package com.tonytaotao.dtsc.common.configuration.datasouce.normal; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; /**
* @author wujintao
*
* Configuration 类似于spring 配置文件,负责注册bean
* ComponentScan 注解类查找规则定义 <context:component-scan/>
* EnableAspectJAutoProxy 激活Aspect 自动代理 <aop:aspectj-autoproxy/>
* proxy-target-class : 默认为false 表示使用JDK 动态代理。如果实现了至少一个接口,Spring 会优先选择使用JDK 动态代理,若果没有实现任何接口,则spring 会选择CGLIB 动态代理,强制使用CGLIB 动态代理,使用以下配置
* exposeProxy : springAOP 只会拦截public 方法,不会拦截provided 和private 方法,并且不会拦截public 方法内部调用的其他方法,也就是说只会拦截代理对象的方法,即增强的是代理对象,而不是原对象, 设置就可以暴露出代理对象,拦截器会获取代理对象,并且将代理对象转换成原对象。从而对内部调用的方法进行增强
* EnableTransactionManagement 启用注解式事务管理 <tx:annotation-driven />
*/
@Configuration
@EnableTransactionManagement
@EnableAspectJAutoProxy(exposeProxy = true)
public class TransationConfig { //@Bean public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("multipleDataSource") DataSource multipleDataSource) { DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); transactionManager.setDataSource(multipleDataSource); return transactionManager; }
}

DBTypeEnum

package com.tonytaotao.dtsc.common.configuration.datasouce; import lombok.Getter; public enum DBTypeEnum { ONE("ONE", "db one"), TWO("TWO", "db two"); DBTypeEnum(String code, String msg) { this.code = code; this.msg = msg; } @Getter private String code; private String msg;
}

DBAnnotation

package com.tonytaotao.dtsc.common.configuration.datasouce; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DBAnnotation { DBTypeEnum dbSource() default DBTypeEnum.ONE;
}

DBAspect

package com.tonytaotao.dtsc.common.configuration.datasouce; import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; import java.lang.reflect.Method; @Component
@Aspect
@Order(-100)
@Slf4j
public class DBAspect { @Pointcut("execution(* com.tonytaotao.dtsc.*.service..*.*(..))") private void pointcut() { } @Before("pointcut()") public void before(JoinPoint joinPoint) { Object target = joinPoint.getTarget(); String methodName = joinPoint.getSignature().getName(); Class<?> clazz = target.getClass(); log.info("before [ class = {}, method = {} ] execute", clazz.getName(), methodName); Class<?>[] parameterTypes = ((MethodSignature)joinPoint.getSignature()).getMethod().getParameterTypes(); try { Method method = clazz.getMethod(methodName, parameterTypes); if (method != null) { if (method.getDeclaringClass().isAnnotationPresent(DBAnnotation.class) && !method.isAnnotationPresent(DBAnnotation.class)) { DBAnnotation dbAnnotation = method.getDeclaringClass().getAnnotation(DBAnnotation.class); DBContextHolder.setDbType(dbAnnotation.dbSource()); log.info("[class = {}, method = {} ] 切换类级数据源 [ {} ] 成功", clazz.getName(), methodName, dbAnnotation.dbSource()); } else if ( method.isAnnotationPresent(DBAnnotation.class)) { DBAnnotation dbAnnotation = method.getAnnotation(DBAnnotation.class); DBContextHolder.setDbType(dbAnnotation.dbSource()); log.info("[class = {}, method = {} ] 切换方法级数据源 [ {} ] 成功", clazz.getName(), methodName, dbAnnotation.dbSource()); } else { DBContextHolder.setDbType(DBTypeEnum.ONE); log.info("[class = {}, method = {} ] 切换默认数据源 [ {} ] 成功", clazz.getName(), methodName, DBTypeEnum.ONE); } } } catch (Exception e) { log.error(" 数据源切换异常", e); } } }

DBContextHolder

package com.tonytaotao.dtsc.common.configuration.datasouce; public class DBContextHolder { private static final ThreadLocal contextHolder = new ThreadLocal<>(); /** * 设置数据源 * @param dbTypeEnum */ public static void setDbType(DBTypeEnum dbTypeEnum) { contextHolder.set(dbTypeEnum.getCode()); } /** * 取得当前数据源 * @return */ public static String getDbType() { return (String) contextHolder.get(); } /** * 清除上下文数据 */ public static void clearDbType() { contextHolder.remove(); }
}

DynamicDataSource

package com.tonytaotao.dtsc.common.configuration.datasouce; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DBContextHolder.getDbType(); }
}

使用方式

只要在 service 实现类的方法上或者类上加上 @DBAnnotation 指定数据源,就能实现自动切换数据源

转载于:https://my.oschina.net/TonyTaotao/blog/2980518

Spring+MybatisPlus实现多数据源相关推荐

  1. spring boot项目自定义数据源,mybatisplus分页、逻辑删除无效解决方法

    Spring Boot项目中数据源的配置可以通过两种方式实现: 1.application.yml或者application.properties配置 2.注入DataSource及SqlSessio ...

  2. Mybatis | Mybatis-plus配置多数据源,连接多数据库

    文章目录 前言 业务逻辑 使用Mybatis实现 使用Mybatis-plus实现 前言 ​ 工作的时候,遇到了需要将一个数据库的一些数据插入或更新到另一个数据库.一开始使用insert into T ...

  3. SpringBoot整合:Druid、MyBatis、MyBatis-Plus、多数据源、knife4j、日志、Redis,Redis的Java操作工具类、封装发送电子邮件等等

    SpringBoot笔记 一.SpringBoot 介绍 1.1.SpringBoot简介 SpringBoot 是一个快速开发的框架, 封装了Maven常用依赖.能够快速的整合第三方框架:简化XML ...

  4. Spring中配置DataSource数据源的几种选择

    Spring中配置DataSource数据源的几种选择 在Spring框架中有如下3种获得DataSource对象的方法: 从JNDI获得DataSource. 从第三方的连接池获得DataSourc ...

  5. Spring(AbstractRoutingDataSource)实现动态数据源切换

    参考:http://linhongyu.blog.51cto.com/6373370/1615895 一.前言 近期一项目A需实现数据同步到另一项目B数据库中,在不改变B项目的情况下,只好选择项目A中 ...

  6. Spring(AbstractRoutingDataSource)实现动态数据源切换--转载

    原始出处:http://linhongyu.blog.51cto.com/6373370/1615895 一.前言 近期一项目A需实现数据同步到另一项目B数据库中,在不改变B项目的情况下,只好选择项目 ...

  7. java多个数据库数据进行访问_通过Spring Boot配置动态数据源访问多个数据库的实现代码...

    之前写过一篇博客<Spring+Mybatis+Mysql搭建分布式数据库访问框架>描述如何通过Spring+Mybatis配置动态数据源访问多个数据库.但是之前的方案有一些限制(原博客中 ...

  8. Spring+Hibernate配置多数据源

    Spring+Hibernate配置多数据源 转载于:https://www.cnblogs.com/zhujiabin/p/4816453.html

  9. 【Spring学习】spring动态配置多数据源

    这段时间在做智能导航的管理系统--运维系统,涉及到连接多个数据库的问题.因为运维系统要用到智能导航的一些功能,我们目前只是简单的将智能导航整合到运维系统中:运维系统有一个自己的数据库,导航也有自己的数 ...

最新文章

  1. 【第一组】第十次冲刺例会纪要
  2. 一个由印度人编写的VC串口类
  3. ubuntu下eclipse的svn插件使用javahl
  4. RecyclerView的优化:RecycledViewPool
  5. 知识图谱基础知识(一): 概念和构建
  6. 计算机合并键功能,Word组合(功能键与Ctrl等组合) -电脑资料
  7. SQL中Case和convert()
  8. 谱聚类、Chameleon聚类、PCCA、SOM、Affinity Propagation
  9. react-json渲染
  10. CentOS 6.X启动流程
  11. iQOO骑士黑版本四月亮相:搭载骁龙855+12G运存
  12. C11头文件threads.h声明了创建和管理线程,信号,条件变量的函数
  13. Redis开发与运维之第八章理解内存(五)
  14. arcgis 循环模型批量处理_科学网-ArcGIS模型构建器批处理操作-张凌的博文
  15. volatile原理:happen before
  16. 关于中国电信天翼开放平台短信接口的一些使用
  17. 怎么解c语言逆向编码,逆向还原C语言代码 练习1
  18. Dolby技术汇总(二) --- Dolby Mobile
  19. HR是这样筛选简历的,不知道就完蛋!
  20. python二进制的位运算符

热门文章

  1. docker centos 无法用systemctl 启动服务的问题
  2. SHELL-命令解释程序
  3. PowerPC VxWorks BSP分析7——image压缩
  4. mysql hy000 1005,mysql – ERROR 1005(HY000):无法创建表(errno:150)
  5. 小白兔写话_聪明的小白兔看图写话
  6. python中的tuple_python 数据类型 - tuple
  7. python urlretrieve登录下载_使用python urlretrieve下载文件
  8. 两个点 定位_深圳Mark点定位的一般原理与步骤
  9. 操作系统中进程并发运行的过程_三种电磁流量计运行过程中常见故障解决详情!...
  10. python 返回字符串长度,当使用特殊字符时,Python返回错误的字符串长度