IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> java切换数据源(多数据源) -> 正文阅读

[Java知识库]java切换数据源(多数据源)

现在要在一个服务里设置两个数据源:oracle和mysql
1.需要写配置文件:
@Controller主要是加载spring配置类
@EnableTransactionManagement事务用法,在访问数据库的service中加@Transactional
@MapperScan指定要变成实现类的接口所在的包,然后包下面的所有接口在编译之后都会生成相应的实现类

@Configuration
@EnableTransactionManagement(order = -200)
@MapperScan("com.csair.mpms.mapper*")
public class MyBatiesPlusConfiguration {

// 精确到 master 目录,以便跟其他数据源隔离
static final String MAPPER_LOCATION = "classpath:mapper/*.xml";

/*
 * 分页插件,自动识别数据库类型
 * 多租户,请参考官网【插件扩展】
 */
@Bean
public PaginationInterceptor paginationInterceptor() {
    PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
    // 开启 PageHelper 的支持
    //paginationInterceptor.setLocalPage(true);
    return paginationInterceptor;
}


@Bean(name = "masterTransactionManager")
    public DataSourceTransactionManager masterTransactionManager() {
        return new DataSourceTransactionManager(masterDataSource());
    }

@Bean(name = "masterSqlSessionFactory")
@Primary
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource)
        throws Exception {
    final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
    sessionFactory.setDataSource(multipleDataSource(masterDataSource(),db2()));
    MybatisConfiguration configuration = new MybatisConfiguration();
    //configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
    configuration.setJdbcTypeForNull(JdbcType.NULL);
    configuration.setMapUnderscoreToCamelCase(true);
    configuration.setCacheEnabled(false);
    sessionFactory.setConfiguration(configuration);
    sessionFactory.setPlugins(new Interceptor[]{ //PerformanceInterceptor(),OptimisticLockerInterceptor()
            paginationInterceptor() //添加分页功能
    });
    sessionFactory.setMapperLocations(new
            PathMatchingResourcePatternResolver()
            .getResources(MAPPER_LOCATION));
    return sessionFactory.getObject();
}

    @Bean(name = "masterDataSource", destroyMethod = "close", initMethod = "init")
    @ConfigurationProperties(prefix = "spring.datasource.druid.db1" )
    public DataSource masterDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

@Bean(name = "db2")
@ConfigurationProperties(prefix = "spring.datasource.druid.db2" )
public DataSource db2 () {
    return DruidDataSourceBuilder.create().build();
}

/**
 * 动态数据源配置
 * @return
 */
@Bean
@Primary
public DataSource multipleDataSource (@Qualifier("masterDataSource") DataSource mpmsDataSource,
                                      @Qualifier("db2") DataSource db2 ) {
    DynamicDataSource dynamicDataSource = new DynamicDataSource();
    Map< Object, Object > targetDataSources = new HashMap<>();
    targetDataSources.put(DBTypeEnum.db1.getValue(), mpmsDataSource );
    targetDataSources.put(DBTypeEnum.db2.getValue(), db2);
    dynamicDataSource.setTargetDataSources(targetDataSources);
    dynamicDataSource.setDefaultTargetDataSource(mpmsDataSource);
    return dynamicDataSource;
}
}

数据源:
DataSourceSwitch文件:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface DataSourceSwitch {
    DBTypeEnum value() default DBTypeEnum.db1;
}

DataSourceSwitchAspect文件:

@Component
@Aspect
@Order(-100)
@Slf4j
public class DataSourceSwitchAspect {

@Pointcut("execution(* com.csair.mpms.service.*.*(..))")
private void db1Aspect() {
}

@Pointcut("execution(* com.csair.mpms.db2Service.*.*(..))")
private void db2Aspect() {
}

@Pointcut("@annotation(DataSourceSwitch)")
private void dataSourceSwitch() {
}

@Before("db1Aspect()")
public void db1(JoinPoint joinPoint) {
    log.info("切换到db1 数据源...");
    setDataSource(joinPoint, DBTypeEnum.db1);
}

@Before("db2Aspect()")
public void db2(JoinPoint joinPoint) {
    log.info("切换到db2 数据源...");
    setDataSource(joinPoint, DBTypeEnum.db2);
}

@Before("dataSourceSwitch()")
public void dataSourceSwitch(JoinPoint joinPoint) {
    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    DataSourceSwitch dataSourceSwitch = methodSignature.getMethod().getAnnotation(DataSourceSwitch.class);
    if (dataSourceSwitch.value() != null) {
        DbContextHolder.setDbType(dataSourceSwitch.value());
        log.info("切换到{} 数据源...", dataSourceSwitch.value().getValue());
    }
}

/**
 * 添加注解方式,如果有注解优先注解,没有则按传过来的数据源配置
 *
 * @param joinPoint
 * @param dbTypeEnum
 */
private void setDataSource(JoinPoint joinPoint, DBTypeEnum dbTypeEnum) {
    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    DataSourceSwitch dataSourceSwitch = methodSignature.getMethod().getAnnotation(DataSourceSwitch.class);
    if (Objects.isNull(dataSourceSwitch) || Objects.isNull(dataSourceSwitch.value())) {
        DbContextHolder.setDbType(dbTypeEnum);
    }
    else {
        log.info("根据注解来切换数据源,注解值为:" + dataSourceSwitch.value());
        switch (dataSourceSwitch.value().getValue()) {
            case "db1":
                DbContextHolder.setDbType(DBTypeEnum.db1);
                break;
            case "db2":
                DbContextHolder.setDbType(DBTypeEnum.db2);
                break;
            default:
                DbContextHolder.setDbType(dbTypeEnum);
        }
    }
}

}

DbContextHolder文件:

public class DbContextHolder {
    private static final ThreadLocal contextHolder = new ThreadLocal<>();
    /**
     * 设置数据源
     * @param dbTypeEnum
     */
    public static void setDbType(DBTypeEnum dbTypeEnum) {
        contextHolder.set(dbTypeEnum.getValue());
    }

    /**
     * 取得当前数据源
     * @return
     */
    public static String getDbType() {
        return (String) contextHolder.get();
    }

    /**
     * 清除上下文数据
     */
    public static void clearDbType() {
        contextHolder.remove();
    }
}

DBTypeEnum文件:

public enum DBTypeEnum {
    db1("db1"), db2("db2");
    private String value;

DBTypeEnum(String value) {
    this.value = value;
}

public String getValue() {
    return value;
}

}

DynamicDataSource文件:

public class DynamicDataSource extends AbstractRoutingDataSource {
    /**
     * 取得当前使用哪个数据源
     * @return
     */
    @Override
    protected Object determineCurrentLookupKey() {
        return DbContextHolder.getDbType();
    }
}

配置文件:

datasource:
    druid:
      db1:
        username: 
        password: 
        driver-class-name: oracle.jdbc.OracleDriver
        url: jdbc:oracle:thin:
        initialSize: 5
        minIdle: 5
        maxActive: 50
        max-wait: 3000
        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
        timeBetweenEvictionRunsMillis: 60000
        # 配置一个连接在池中最小生存的时间,单位是毫秒
        minEvictableIdleTimeMillis: 300000
        validationQuery: SELECT 1 FROM DUAL
      db2:
        type: com.alibaba.druid.pool.DruidDataSource            # 当前数据源操作类型
        driver-class-name: com.mysql.cj.jdbc.Driver              # mysql驱动包
        url: 
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:09:53  更:2022-04-09 18:14:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:07:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码