Springboot +Mybatis + DynamicDataSource 根据数据库实现数据源配置和切换

DynamicDataSource 动态数据源

需求:

数仓项目需要大致检验数据同步的正确性,应用数据库MySQL有多台,数仓数据库Postgres数据库一台。需要检验MySQL各个库中的表条数与postgres中的表条数是否一致。

问题:

Mybatis+MySQL操作每个数据库,需要配置每个数据库的数据源,如配置 url:jdbc://mysql:localhost:8081/user 。
Postgres则没有此烦恼,所有表均在一个库中。 只需要配置一次数据源。
但是MySQL业务数据存储到不同服务器上,且每台数据库服务器上有数百个库。如果使用常规的Springboot + mybatis,通过application.yml来配置数据源,显然不切实际。因此,也考虑过使用原生的jdbc来操纵数据库,但是频繁创建数据源和连接数据库存在性能问题。

解决方案:

使用动态DynamicDataSource ,将数据源信息存储至postgres中一个映射表,通过读取映射来配置数据源。最后,通过key的值来切换数据源,实现数据增删改查。

实现过程

pom.xml

 
    
        org.postgresql
        postgresql
        ${postgresql.version}
    
    
    
        mysql
        mysql-connector-java
        runtime
        8.0.13
    
    
    
        org.mybatis.spring.boot
        mybatis-spring-boot-starter
        ${starter.mybatis.spring.version}
    
    
    
        com.github.yeecode.dynamicdatasource
        DynamicDataSource
        1.3.0
    

配置applicaiton.yml设置默认数据源

dynamicDataSource:
  default:
    url: jdbc:postgresql://localhost:5432/postgres
    driverClassName: org.postgresql.Driver
    username: 
    password: 

配置spirngboot启动器

1.去除自动配置数据源

 @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) 

2.扫描包

@ComponentScan(basePackages = {"com.github.yeecode.dynamicdatasource","业务包"})

新增数据源

public void addDynamicDataSource(List checkResultList) {
    String pgDriverClass = "org.postgresql.Driver";
    String pgUrl = "jdbc:postgresql://localhost:5432/postgres";
    String pgUserName = "";
    String pgPassword = "";
    List allDataSource = getAllDataSource(checkResultList);
    if (CollectionUtils.isEmpty(allDataSource)) {
        return;
    }

    //-----------------------    Mysql 数据源    ---------------------
    for (DataSourceInfo dataSourceInfo : allDataSource) {
        String name = dataSourceInfo.getHostName() + " " + dataSourceInfo.getDatabaseName(); //根据host databasename组合来查找对应的数据源
        com.github.yeecode.dynamicdatasource.model.DataSourceInfo mysqlDynamicDataSourceInfo = new com.github.yeecode.dynamicdatasource.model.DataSourceInfo(name, dataSourceInfo.getDriverClassName(), dataSourceInfo.getUrl(), dataSourceInfo.getUsername(), dataSourceInfo.getPassword());
        dynamicDataSource.addDataSource(mysqlDynamicDataSourceInfo, true);
    }


    //-----------------------    Postgres数据源    ---------------------
    com.github.yeecode.dynamicdatasource.model.DataSourceInfo pgDynamicDataSourceInfo = new com.github.yeecode.dynamicdatasource.model.DataSourceInfo("postgres", pgDriverClass, pgUrl, pgUserName, pgPassword);
    dynamicDataSource.addDataSource(pgDynamicDataSourceInfo, true);


}

操作数据库

public List check() {
    List resultList = new LinkedList<>(); //存储检查结果

    List dataSourceInfoList = checkResultMapper.listByGroup();  // 根据映射表获取数据源信息

    dataSourceInfoService.addDynamicDataSource(dataSourceInfoList); // 新增数据源

    List mappingList = checkResultMapper.findAll();

    if (CollectionUtils.isEmpty(mappingList)) {
        return null;
    }

    //-----------------------    根据每个表来查询对应的条数    ---------------------
    for (CheckResult checkResult : mappingList) {
        String originDatabase = checkResult.getOriginDatabase();
        String originDatabaseHost = checkResult.getOriginDatabaseHost();
        String originTableName = checkResult.getOriginTableName();
        String targetTableName = checkResult.getTargetTableName();
        String timeFieldName = checkResult.getTimeFieldName();
        String timeFieldValue = checkResult.getTimeFieldValue();
        String originCheckSQL = getCheckSQL(originTableName, timeFieldName, timeFieldValue);
        String targetCheckSQL = getCheckSQL(targetTableName, timeFieldName, timeFieldValue);

        //-----------------------    计算源数据库条数    ---------------------
        String datasourceKey = originDatabaseHost + " " + originDatabase;  //根据该key来切换数据源
        dynamicDataSource.switchDataSource(datasourceKey);
        long originCount = commonService.getCount(originCheckSQL); // 源库条数

        //-----------------------    计算目标库条数    ---------------------
        dynamicDataSource.switchDataSource("postgres");
        long targetCount = commonService.getCount(targetCheckSQL); // 目标库条数

        //-----------------------    汇总结果    ---------------------
        checkResult.setOriginCount(originCount);
        checkResult.setTargetCount(targetCount);
        checkResult.setSubValue(targetCount - originCount);
        if (originCount == targetCount) {
            checkResult.setIsCorrect(true);
        } else {
            checkResult.setIsCorrect(false);
        }
        resultList.add(checkResult);

    }
    return resultList;
}

第一次写文章,如有更好建议和意见,请多多指教!

你可能感兴趣的:(mybatis,数据库,mysql,spring,boot,java)