前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >spring boot 配置 多数据源

spring boot 配置 多数据源

原创
作者头像
特特
发布于 2022-08-14 15:41:10
发布于 2022-08-14 15:41:10
5400
举报
文章被收录于专栏:特特的专栏特特的专栏

1. 前言

在日常生活中,我们不可避免要在工程中配置多个数据源,下面我就给大家讲一下怎么在spring boot里面配置多数据源,并且在文章结尾给出一个github的demo,希望对大家有所帮助

2. application.yml 配置多个数据库

代码语言:yaml
AI代码解释
复制
spring:
  datasource:
    write:
      url: jdbc:mysql://192.168.31.155:3306/test_1?characterEncoding=UTF-8&useSSL=false
      username: root
      password: root
    read:
      url: jdbc:mysql://192.168.31.155:3306/test_2?characterEncoding=UTF-8&useSSL=false
      username: root
      password: root

3. spring读取配置文件

代码语言:shell
AI代码解释
复制
package com.multi.datasource.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * @create: 2021-01-14 14:56
 **/
@ConfigurationProperties(prefix = "spring.datasource.read")
@Data
public class DataSourceReadProperties {

    private String url;
    private String username;
    private String password;
}
代码语言:shell
AI代码解释
复制
package com.multi.datasource.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * @create: 2021-01-14 14:56
 **/
@ConfigurationProperties(prefix = "spring.datasource.write")
@Data
public class DataSourceWriteProperties {

    private String url;
    private String username;
    private String password;
}

4. 数据源配置

代码语言:shell
AI代码解释
复制
package com.multi.datasource.config;

import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * @create: 2021-01-14 14:55
 **/
@Configuration
public class DataSourceConfig {

    @Bean("dataSourceReadProperties")
    @ConditionalOnProperty(prefix = "spring.datasource.read", name = {"url", "username", "password"})
    public DataSourceReadProperties dataSourceReadProperties() {
        DataSourceReadProperties dataSourceReadProperties = new DataSourceReadProperties();
        return dataSourceReadProperties;
    }

    @Bean("dataSourceWriteProperties")
    @ConditionalOnProperty(prefix = "spring.datasource.write", name = {"url", "username", "password"})
    public DataSourceWriteProperties dataSourceWriteProperties() {
        DataSourceWriteProperties dataSourceWriteProperties = new DataSourceWriteProperties();
        return dataSourceWriteProperties;
    }

    @Bean("dataSourceRead")
    @ConditionalOnBean(name = "dataSourceReadProperties")
    public DataSource getDataSourceRead(@Qualifier("dataSourceReadProperties") DataSourceReadProperties dataSourceReadProperties) {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(dataSourceReadProperties.getUrl());
        dataSource.setUsername(dataSourceReadProperties.getUsername());
        dataSource.setPassword(dataSourceReadProperties.getPassword());
        return dataSource;
    }

    @Bean("dataSourceWrite")
    @ConditionalOnBean(name = "dataSourceWriteProperties")
    public DataSource getDataSourceWrite(@Qualifier("dataSourceWriteProperties") DataSourceWriteProperties dataSourceWriteProperties) {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(dataSourceWriteProperties.getUrl());
        dataSource.setUsername(dataSourceWriteProperties.getUsername());
        dataSource.setPassword(dataSourceWriteProperties.getPassword());
        return dataSource;
    }


    /**
     * 设置数据源路由,通过该类中的determineCurrentLookupKey决定使用哪个数据源
     */
    @Bean("routingDataSource")
    public AbstractRoutingDataSource routingDataSource(@Qualifier("dataSourceWrite") DataSource dataSourceWrite,
                                                       @Qualifier("dataSourceRead") DataSource dataSourceRead) {
        MyAbstractRoutingDataSource proxy = new MyAbstractRoutingDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>(2);
        targetDataSources.put(DbContextHolder.WRITE, dataSourceWrite);
        targetDataSources.put(DbContextHolder.READ, dataSourceRead);
        proxy.setDefaultTargetDataSource(dataSourceWrite);
        proxy.setTargetDataSources(targetDataSources);
        return proxy;
    }

    /**
     * 多数据源需要自己设置sqlSessionFactory
     */
    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("routingDataSource") AbstractRoutingDataSource routingDataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(routingDataSource);
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // mybatis的XML的配置
        bean.setMapperLocations(resolver.getResources("classpath*:mapper/*Mapper.xml"));
        return bean.getObject();
    }

    /**
     * 设置事务,事务需要知道当前使用的是哪个数据源才能进行事务处理
     */
    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("routingDataSource") AbstractRoutingDataSource routingDataSource) {
        return new DataSourceTransactionManager(routingDataSource);
    }
}

5.多数据源切换配置

代码语言:shell
AI代码解释
复制
package com.multi.datasource.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * 这里切换读/写模式
 * 原理是利用ThreadLocal保存当前线程是否处于读模式(通过开始READ_ONLY注解在开始操作前设置模式为读模式,
 * 操作结束后清除该数据,避免内存泄漏,同时也为了后续在该线程进行写操作时任然为读模式
 *
 * @author zxliuyu
 */
@Slf4j
public class DbContextHolder {

    public static final String WRITE = "write";
    public static final String READ = "read";

    private static ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public static void setDbType(String dbType) {
        if (StringUtils.isBlank(dbType)) {
            log.error("DbContextHolder dbType is null");
        }
        contextHolder.set(dbType);
    }

    public static String getDbType() {
        return StringUtils.isBlank(contextHolder.get()) ? WRITE : contextHolder.get();
    }

    public static void clearDbType() {
        contextHolder.remove();
    }
}
代码语言:shell
AI代码解释
复制
package com.multi.datasource.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

@Slf4j
public class MyAbstractRoutingDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        String typeKey = DbContextHolder.getDbType();
        if (typeKey.equals(DbContextHolder.WRITE)) {
            log.info("dataSource is use write");
            return typeKey;
        }
        log.info("dataSource is use read");
        return DbContextHolder.READ;
    }
}

6. 通过注解指定数据源

代码语言:shell
AI代码解释
复制
package com.multi.datasource.config;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @create: 2021-01-14 17:22
 **/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ReadOnly {
}
代码语言:shell
AI代码解释
复制
package com.multi.datasource.config;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Slf4j
public class ReadOnlyInterceptor implements Ordered {

    @Around("@annotation(readOnly)")
    public Object setRead(ProceedingJoinPoint joinPoint, ReadOnly readOnly) throws Throwable {
        try {
            DbContextHolder.setDbType(DbContextHolder.READ);
            return joinPoint.proceed();
        } finally {
            // 清楚DbType一方面为了避免内存泄漏,更重要的是避免对后续在本线程上执行的操作产生影响
            DbContextHolder.clearDbType();
            log.info("remove threadLocal");
        }
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

7. github地址

https://github.com/constantRAIN/multi-data-source

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
NeurIPS 2021:半监督节点分类中的拓扑不平衡学习
Topology-Imbalance Learning for Semi-Supervised Node Classifification
Houye
2021/11/17
9340
NeurIPS 2021:半监督节点分类中的拓扑不平衡学习
FBRT-YOLO:面向实时航拍图像检测的轻量高效目标检测框架
具备视觉能力的嵌入式飞行设备在众多应用中变得至关重要。在航空图像检测领域,尽管许多现有方法已部分解决了小目标检测的问题,但在优化小目标检测以及平衡检测精度与效率方面仍面临挑战。这些问题是实时航空图像检测发展的关键障碍。在本文中,我们提出了一系列新的用于航空图像检测的实时检测器,命名为FBRT-YOLO,旨在解决检测精度与效率之间的不平衡问题。我们的方法包含两个轻量级模块:特征互补映射模块(FCM)和多核感知单元(MKP),旨在增强航空图像中小目标的物体感知能力。FCM侧重于缓解深层网络中小目标信息丢失导致的信息不平衡问题。它旨在将目标的空间位置信息更深入地集成到网络中,更好地与深层语义信息对齐,以提高小目标的定位精度。我们引入了MKP,它利用不同大小的卷积核来增强不同尺度目标之间的关系,并提高对不同尺度目标的感知能力。在Visdrone、UAVDT和AI-TOD等三个主要航空图像数据集上的广泛实验结果表明,FBRT-YOLO在性能和速度方面均优于各种实时检测器。代码将在https://github.com/galaxy-oss/FCM上提供。
AI浩
2025/06/11
1070
FBRT-YOLO:面向实时航拍图像检测的轻量高效目标检测框架
今日 Paper | 社交媒体谣言检测;连续手语识别;细粒度服装相似性学习;混合图神经网络等
论文名称:Rumor Detection on Social Media with Bi-Directional Graph Convolutional Networks
AI科技评论
2020/02/24
7730
今日 Paper | 社交媒体谣言检测;连续手语识别;细粒度服装相似性学习;混合图神经网络等
Arxiv机器学习论文摘要10篇(2019-7-17)
原文标题:Two-stage Optimization for Machine Learning Workflow
Jarvis Cocker
2019/07/17
1.2K0
【NeurIPS】四篇好文简读-专题9
Language models enable zero-shot prediction of the effects of mutations on protein function 论文摘要:
智能生信
2022/05/23
5590
【NeurIPS】四篇好文简读-专题9
ECCV 2022 | PTSEFormer : 针对视频目标检测的渐进式时空增强模型
近年来出现了一种应用上下帧来提高检测的性能的研究趋势,即视频目标检测。现有的方法通常会融合时序特征以增强检测性能。然而,这些方法通常缺乏来自相邻帧的空间信息,并且存在特征融合不足的问题。
用户1324186
2022/11/07
2K0
ECCV 2022 | PTSEFormer : 针对视频目标检测的渐进式时空增强模型
COLING2022 | 角色感知的渐进式谣言判别框架
每天给你送来NLP技术干货! ---- ©作者 | 社媒派SMP 来源 | 社媒派SMP 排版 | PaperWeekly 论文标题: A Progressive Framework for Role-Aware Rumor Resolution 论文作者: 陈蕾(复旦大学),李冠颖(复旦大学),魏忠钰(复旦大学),杨洋(浙江大学),周葆华(复旦大学),张奇(复旦大学),黄萱菁(复旦大学) 收录会议: The 29th International Conference on Computational L
zenRRan
2022/09/13
5600
COLING2022 | 角色感知的渐进式谣言判别框架
创造家庭大和谐,用 AI 给爹妈做个辟谣助手
这些标题在具有一定科学素养的年轻人看来,根本不用点开,就知道是谣言或者过度夸张,但这些文章却在父母辈的微信群和朋友圈里每天疯传着。
HyperAI超神经
2019/11/30
3820
一文了解复旦大学DISC实验室4篇COLING 2022论文内容
每天给你送来NLP技术干货! ---- 来自:复旦DISC COLING 2022 国际计算语言学大会 (Inteational Conference on Computational Linguistics,COLING),是自然语言处理和计算语言学领域的重要国际学术会议,每两年召开一次,1965年第一届召开以来,COLING已成功地举办了29届。2022年秋季, COLING将以混合形式在韩国庆州举行, 所有参与者都可以在会场现场或虚拟加入。 在COLING 2022中, 复旦大学数据智能与社会计算
zenRRan
2022/08/26
1.1K0
一文了解复旦大学DISC实验室4篇COLING 2022论文内容
你的模型是不是换个场景就不行了?CAT 的完美设计解决类内偏差,场景自适应的目标检测就这么诞生了
Foggy Cityscapes数据集上,作者获得了52.5 mAP,相比于最先进方法的51.2 mAP,这是一个显著的提升。
集智书童公众号
2024/04/25
7950
你的模型是不是换个场景就不行了?CAT 的完美设计解决类内偏差,场景自适应的目标检测就这么诞生了
智慧工地:2PCNet,昼夜无监督域自适应目标检测(附原代码)
由于缺乏夜间图像注释,夜间目标检测是一个具有挑战性的问题。尽管有几种领域自适应方法,但实现高精度结果仍然是一个问题。
计算机视觉研究院
2023/09/20
5991
智慧工地:2PCNet,昼夜无监督域自适应目标检测(附原代码)
计算机视觉最新进展概览(2021年7月11日到2021年7月17日)
自动驾驶汽车的目标检测通常基于摄像头图像和激光雷达输入,通常用于训练深度人工神经网络等预测模型,用于目标识别决策、速度调节等。 这种决策中的一个错误可能是破坏性的; 因此,通过不确定性测度来衡量预测模型决策的可靠性至关重要。 在深度学习模型中,不确定性通常用于衡量分类问题。 然而,自动驾驶中的深度学习模型往往是多输出回归模型。 因此,我们提出了一种新的方法,即预测表面不确定度(PURE)来测量这类回归模型的预测不确定度。 我们将目标识别问题表述为一个具有多个输出的回归模型,用于在二维摄像机视图中寻找目标位置。 为了进行评估,我们修改了三个广泛应用的目标识别模型(即YoLo、SSD300和SSD512),并使用了KITTI、Stanford Cars、Berkeley DeepDrive和NEXET数据集。 结果显示,预测面不确定性与预测精度之间存在显著的负相关关系,表明不确定性对自动驾驶决策有显著影响。
狼啸风云
2021/07/20
5840
ICML2020 | Self-PU learning:把三个自监督技巧扔进PU learning
今天给大家介绍的是德州农工大学Xuxi Chen等人在ICML2020上发表的一篇名为“Self-PU: Self Boosted and Calibrated Positive-Unlabeled Training”的文章。许多现实世界的应用领域必须解决Positive-Unlabeled (PU) learning问题,即从大量的无标记数据和少数有标记的正示例中训练一个二分类器。虽然目前最先进的方法采用了重要性重加权来设计各种风险估计器,但它们忽略了模型本身的学习能力,而这本来可以提供可靠的监督。这促使作者提出了一种新型的Self-PU learning框架,该框架将PU learning与self-training无缝结合。self- PU learning包含了三个self导向的模块:自适应地发现和增强确信的正/负例子的self-paced训练算法; self-calibrated实例感知损失;以及一个引入教师-学生学习作为PU学习有效正则化的self-distillation方案。作者在通用PU learning基准(MNIST和CIFAR-10)上展示了Self-PU的最先进性能,与最新的竞争对手相比具有优势。此外,还研究了PU学习在现实世界中的应用,即对阿尔茨海默病的脑图像进行分类。与现有方法相比,Self-PU在著名的阿尔茨海默病神经成像(ADNI)数据库上获得了显著改进的结果。
智能生信
2021/05/17
2.8K0
ICML2020 | Self-PU learning:把三个自监督技巧扔进PU learning
[一周论文精选] 5篇值得读的GNN论文
本期为大家推荐5篇论文,论文主题涉及到当前研究最新动向,如异质图上的新基准,能够平衡不类别节点数量的最新GNN模型,GNN同MLP模型的对比,解决图表示学习关于异构性、归纳性和效率问题的方法,图表示学习的GNN的外推分析等。
Houye
2021/04/22
1.3K0
[一周论文精选] 5篇值得读的GNN论文
Bioinformatics|MolFeSCue:基于小样本对比学习增强有限和不平衡数据下的分子性质预测
2024年2月29日,吉林大学周丰丰教授团队在Bioinformatics上发表文章MolFeSCue: enhancing molecular property prediction in data-limited and imbalanced contexts using few-shot and contrastive learning。
智药邦
2024/04/28
5300
Bioinformatics|MolFeSCue:基于小样本对比学习增强有限和不平衡数据下的分子性质预测
CoVLM:利用视觉语言模型的共识进行半监督多模态假新闻检测 !
社交媒体上的假新闻蔓延使得假新闻检测成为保持信息完整性的关键任务,保护公共言论,并防止信任侵蚀[1]。生成假新闻的越来越受欢迎的方法是将真实图像与误导/不正确的标题配对,因为这样需要最小的努力和技术专业知识。图1展示了来自基准新闻CLIPings数据集[4]的真实和假图像-文本配对的一些例子。假新闻通常在视觉内容和伴随文本之间存在差异,而真实新闻则往往在图像和文本之间具有连贯的关系。
未来先知
2024/11/06
2810
CoVLM:利用视觉语言模型的共识进行半监督多模态假新闻检测 !
万字长文带你解读『虚假新闻检测』最新进展
互联网时代,假新闻铺天盖地,而且极具迷惑性,因此假新闻检测任务对逻辑的判断,以及常识的学习都需要很高的要求。今天和大家分享『虚假新闻检测』相关研究进展,包括创新点、改进点等
NewBeeNLP
2021/01/18
2.4K0
基于连接感知的实时困倦分类图神经网络
疲劳驾驶是导致交通事故的主要原因之一。脑电图(EEG)是一种直接从大脑活动中检测睡意的方法,已广泛用于实时检测驾驶员的睡意。最近的研究表明,使用基于脑电图数据构建的大脑连接图来预测困倦状态的巨大潜力。然而,传统的脑连接网络与下游预测任务无关。本文提出了一种使用自注意机制的连接感知图神经网络(CAGNN),该网络可以通过端到端训练生成与任务相关的连接网络。
是Dream呀
2025/03/16
560
基于连接感知的实时困倦分类图神经网络
半监督学习将再度兴起!谷歌祭出大杀器:无监督数据增强
近日,谷歌AI发布了一篇博文,博文指出可以对无标注数据执行数据增强,从而显著提高了半监督学习(SSL)的性能,因此研究人员相信"半监督学习将再度兴起!"
磐创AI
2019/07/17
1.1K0
半监督学习将再度兴起!谷歌祭出大杀器:无监督数据增强
用飞桨检测谣言,新技能get!
https://aistudio.baidu.com/aistudio/projectdetail/263255
用户1386409
2020/03/04
8070
推荐阅读
NeurIPS 2021:半监督节点分类中的拓扑不平衡学习
9340
FBRT-YOLO:面向实时航拍图像检测的轻量高效目标检测框架
1070
今日 Paper | 社交媒体谣言检测;连续手语识别;细粒度服装相似性学习;混合图神经网络等
7730
Arxiv机器学习论文摘要10篇(2019-7-17)
1.2K0
【NeurIPS】四篇好文简读-专题9
5590
ECCV 2022 | PTSEFormer : 针对视频目标检测的渐进式时空增强模型
2K0
COLING2022 | 角色感知的渐进式谣言判别框架
5600
创造家庭大和谐,用 AI 给爹妈做个辟谣助手
3820
一文了解复旦大学DISC实验室4篇COLING 2022论文内容
1.1K0
你的模型是不是换个场景就不行了?CAT 的完美设计解决类内偏差,场景自适应的目标检测就这么诞生了
7950
智慧工地:2PCNet,昼夜无监督域自适应目标检测(附原代码)
5991
计算机视觉最新进展概览(2021年7月11日到2021年7月17日)
5840
ICML2020 | Self-PU learning:把三个自监督技巧扔进PU learning
2.8K0
[一周论文精选] 5篇值得读的GNN论文
1.3K0
Bioinformatics|MolFeSCue:基于小样本对比学习增强有限和不平衡数据下的分子性质预测
5300
CoVLM:利用视觉语言模型的共识进行半监督多模态假新闻检测 !
2810
万字长文带你解读『虚假新闻检测』最新进展
2.4K0
基于连接感知的实时困倦分类图神经网络
560
半监督学习将再度兴起!谷歌祭出大杀器:无监督数据增强
1.1K0
用飞桨检测谣言,新技能get!
8070
相关推荐
NeurIPS 2021:半监督节点分类中的拓扑不平衡学习
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档