Spring+Mybatis项目中通过继承AbstractRoutingDataSource实现数据库热切换
admin
2023-05-30 04:00:16
0

  在做ERP项目的时候有个需求是能够管理和切换账套,一个账套就是一个数据库,那么就需要实现数据库的热切换。网上找了很多资料再结合项目的具体需求实现了一个还算比较好用的数据库热切换。

  原理是首先继承AbstractRoutingDataSource并实现determineCurrentLookupKey方法,方法的内容为

protected Object determineCurrentLookupKey() {
    return DataSourceContextHolder.getDataSourceType();
}

这个方法的功能是再执行sql之前spring会先执行这个方法,并从数据源Map中通过这个方法返回的key去确定要使用的数据源。

  再新增一个方法:refreshDataSources

private void refreshDataSources(List databaseList) {
    if (databaseList != null && databaseList.size() > 0) {
        BasicDataSource templateDataSource = (BasicDataSource) this.context.getBean("dataSource");//模板数据源

        Map targetDataSources = new HashMap();
        for (String database : databaseList) {
            BasicDataSource dataSource = new BasicDataSource();
            dataSource.setDriverClassName(templateDataSource.getDriverClassName());
            dataSource.setUrl(regexReplaceUrl(templateDataSource.getUrl(), database));
            dataSource.setUsername(templateDataSource.getUsername());
            dataSource.setPassword(templateDataSource.getPassword());
            dataSource.setMaxActive(templateDataSource.getMaxActive());
            dataSource.setMaxIdle(templateDataSource.getMaxIdle());
            dataSource.setDefaultAutoCommit(templateDataSource.getDefaultAutoCommit());
            dataSource.setTimeBetweenEvictionRunsMillis(templateDataSource.getTimeBetweenEvictionRunsMillis());
            dataSource.setMinEvictableIdleTimeMillis(templateDataSource.getMinEvictableIdleTimeMillis());
            targetDataSources.put(database, dataSource);
        }
        targetDataSources.put("sycerp_system", templateDataSource); //加入默认dataSource

        this.setTargetDataSources(targetDataSources);
        this.setDefaultTargetDataSource(targetDataSources.get("sycerp_system"));
    }
    super.afterPropertiesSet();
}


// 这个方法的功能是将已经配置好的默认数据源的url中的database段替换会databaseList中的字符串
private String regexReplaceUrl(String url, String database) {
    return Pattern.compile("[/][a-z0-9_]+[\\?]").matcher(url).replaceAll("/" + database + "?");
}

这个方法的功能是将传入的databaseList(需要热切换的数据库名称列表),除了datasource的url需要替换外其他的属性都通过默认配置好的数据源中配置的属性,最后将封装好的数据源集合放入targetDataSources中,然后调用afterPropertiesSet方法刷新数据源,afterPropertiesSet的具体内容可以查看源码。

其中,这段代码中的context对象是通过实现ApplicationContextAware接口的setApplicationContext方法取得的,spring会自动注入applicationContext对象。

  然后就是配置,我们还是按照常规的spring整合mybatis的配置方法,只是多了一个数据源的配置

id="dynamicDataSource" class="cn.jteee.sycerp.server.datasources.DynamicDataSource">
   name="targetDataSources">
       
           value-ref="dataSource" key="sycerp_system"/>
       
   

   name="defaultTargetDataSource" ref="dataSource"/>

其中dynamicDataSource就是上面实现AbstractRoutingDataSource的类,里面ref的dataSource就是默认的数据源,其他配置数据ref的地方就使用这个dynamicDataSource,而不是dataSource。

  最后就是怎么使用。因为dynamicDataSource已经被spring管理起来了,所以,我们只需要在我们会用到的地方先生成一个数据库名称列表,可以从其他数据库中查询,然后调用refreshDataSources方法,最后调用

DataSourceContextHolder.setDataSourceType("你要切换的数据库名称");

下面是DataSourceContextHolder的代码

public class DataSourceContextHolder {

    private static final ThreadLocal contextHolder = new ThreadLocal();

    public static void setDataSourceType(String dataSourceType) {
        contextHolder.set(dataSourceType);
    }

    public static String getDataSourceType() {
        return contextHolder.get();
    }

    public static void clearDataSourceType() {
        contextHolder.remove();
    }

}

  到此,一个完整的实现数据库热切换的功能就全部实现了,有其他特定的需求可以在此基础上修改。

相关内容

热门资讯

2026年专业可靠的抖音指环遥... 探索智能遥控新纪元:揭秘指环遥控器的核心技术演进 想象一下:当你在公园记录孩子的童真笑容,双手却...
原创 秦... 摘要:建文软件以“360°可视化”为核心引擎,助力秦皇岛多信建筑重塑“AI+工程管理”新范式。依托覆...
聚力新通信 智启6G未来 6G... 2026年5月21日,以“聚力新通信·智启6G未来”为主题的6G产业创新发展大会暨第九届“绽放杯”上...
别让伪科学教育,毁了孩子的未来... 从“量子波动速读”到“脑屏开发”,再到各类“脑波智慧机”“照相记忆”“蒙眼识字”培训,以及“近红外光...
宁东方案入选工信部“链网协同”... 5月20日,记者从宁东能源化工基地管委会获悉,近日,由宁东科技创业投资有限公司牵头申报的“基于工业互...
美国欲在古巴重演“委内瑞拉剧本... 美国起诉劳尔·卡斯特罗引发外界关注,继对委内瑞拉、伊朗采取行动之后,美国又要对古巴动手吗?将引发哪些...
美国驻丹麦大使:特朗普已排除对... △美国驻丹麦大使肯尼思·豪韦里当地时间5月21日,美国驻丹麦大使肯尼思·豪韦里在格陵兰岛首府努克新美...
警惕“银狐”木马病毒来袭,涉违... 近日,国家计算机病毒应急处理中心发布关于针对我国用户的“银狐”系列木马病毒攻击活动的预警报告。国家计...
ASML首席执行官Fouque... IT之家 5 月 21 日消息,ASML(阿斯麦)首席执行官 Christophe Fouquet(...
特斯拉监督版FSD官宣入华!智... 特斯拉官方5月21日通过社交媒体公布了监督版全自动驾驶系统(FSD)的最新全球化布局,其中明确提及该...