我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Spring Boot怎么整合多数据源

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Spring Boot怎么整合多数据源

本篇内容主要讲解“Spring Boot怎么整合多数据源”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring Boot怎么整合多数据源”吧!

前言:

什么是多数据源?最常见的单一应用中最多涉及到一个数据库,即是一个数据源(Datasource)。那么顾名思义,多数据源就是在一个单一应用中涉及到了两个及以上的数据库了。

其实在配置数据源的时候就已经很明确这个定义了,如以下代码:

@Bean(name = "dataSource")    public DataSource dataSource() {        DruidDataSource druidDataSource = new DruidDataSource();        druidDataSource.setUrl(url);        druidDataSource.setUsername(username);        druidDataSource.setDriverClassName(driverClassName);        druidDataSource.setPassword(password);        return druidDataSource;    }

url、username、password这三个属性已经唯一确定了一个数据库了,DataSource则是依赖这三个创建出来的。则多数据源即是配置多个DataSource(暂且这么理解)。

何时用到多数据源

正如前言介绍到的一个场景,相信大多数做过医疗系统的都会和HIS打交道,为了简化护士以及医生的操作流程,必须要将必要的信息从HIS系统对接过来,据我了解的大致有两种方案如下:

HIS提供视图,比如医护视图、患者视图等,而此时其他系统只需要定时的从HIS视图中读取数据同步到自己数据库中即可。

  • HIS提供接口,无论是webService还是HTTP形式都是可行的,此时其他系统只需要按照要求调接口即可。

  • 很明显第一种方案涉及到了至少两个数据库了,一个是HIS数据库,一个自己系统的数据库,在单一应用中必然需要用到多数据源的切换才能达到目的。

当然多数据源的使用场景还是有很多的,以上只是简单的一个场景。

整合单一的数据源

本文使用阿里的数据库连接池druid,添加依赖如下:

<!--druid连接池--><dependency>   <groupId>com.alibaba</groupId>   <artifactId>druid-spring-boot-starter</artifactId>   <version>1.1.9</version></dependency>

阿里的数据库连接池非常强大,比如数据监控、数据库加密等等内容,本文仅仅演示与Spring Boot整合的过程,一些其他的功能后续可以自己研究添加。

Druid连接池的starter的自动配置类是DruidDataSourceAutoConfigure,类上标注如下一行注解:

@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})

@EnableConfigurationProperties这个注解使得配置文件中的配置生效并且映射到指定类的属性。

”DruidStatProperties中指定的前缀是spring.datasource.druid,这个配置主要是用来设置连接池的一些参数。

DataSourceProperties中指定的前缀是spring.datasource,这个主要是用来设置数据库的url、username、password等信息。

因此我们只需要在全局配置文件中指定数据库的一些配置以及连接池的一些配置信息即可,前缀分别是spring.datasource.druid、spring.datasource,以下是个人随便配置的(application.properties):

spring.datasource.url=jdbc:mysql://120.26.101.xxx:3306/xxx?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghaispring.datasource.username=rootspring.datasource.password=xxxxspring.datasource.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.driver-class-name=com.mysql.jdbc.Driver#初始化连接大小spring.datasource.druid.initial-size=0#连接池最大使用连接数量spring.datasource.druid.max-active=20#连接池最小空闲spring.datasource.druid.min-idle=0#获取连接最大等待时间spring.datasource.druid.max-wait=6000spring.datasource.druid.validation-query=SELECT 1#spring.datasource.druid.validation-query-timeout=6000spring.datasource.druid.test-on-borrow=falsespring.datasource.druid.test-on-return=falsespring.datasource.druid.test-while-idle=true#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒spring.datasource.druid.time-between-eviction-runs-millis=60000#置一个连接在池中最小生存的时间,单位是毫秒spring.datasource.druid.min-evictable-idle-time-millis=25200000#spring.datasource.druid.max-evictable-idle-time-millis=#打开removeAbandoned功能,多少时间内必须关闭连接spring.datasource.druid.removeAbandoned=true#1800秒,也就是30分钟spring.datasource.druid.remove-abandoned-timeout=1800#<!-- 1800秒,也就是30分钟 -->spring.datasource.druid.log-abandoned=truespring.datasource.druid.filters=mergeStat

在全局配置文件application.properties文件中配置以上的信息即可注入一个数据源到Spring Boot中。其实这仅仅是一种方式,下面介绍另外一种方式。

”在自动配置类中DruidDataSourceAutoConfigure中有如下一段代码:

@Bean(initMethod = "init")    @ConditionalOnMissingBean    public DataSource dataSource() {        LOGGER.info("Init DruidDataSource");        return new DruidDataSourceWrapper();    }

@ConditionalOnMissingBean和@Bean这两个注解的结合,意味着我们可以覆盖,只需要提前在IOC中注入一个DataSource类型的Bean即可。

”因此我们在自定义的配置类中定义如下配置即可:

    @ConfigurationProperties(prefix = "spring.datasource")    @Bean    public DataSource dataSource(){        //做一些其他的自定义配置,比如密码加密等......        return new DruidDataSource();    }

以上介绍了两种数据源的配置方式,第一种比较简单,第二种适合扩展,按需选择。

整合Mybatis

Spring Boot 整合Mybatis其实很简单,简单的几步就搞定,首先添加依赖:

<dependency>     <groupId>org.mybatis.spring.boot</groupId>     <artifactId>mybatis-spring-boot-starter</artifactId>     <version>2.0.0</version></dependency>

第二步找到自动配置类MybatisAutoConfiguration,有如下一行代码:

@EnableConfigurationProperties(MybatisProperties.class)

老套路了,全局配置文件中配置前缀为mybatis的配置将会映射到该类中的属性。

”可配置的东西很多,比如XML文件的位置、类型处理器等等,如下简单的配置:

mybatis.type-handlers-package=com.demo.typehandlermybatis.configuration.map-underscore-to-camel-case=true

如果需要通过包扫描的方式注入Mapper,则需要在配置类上加入一个注解:@MapperScan,其中的value属性指定需要扫描的包。

直接在全局配置文件配置各种属性是一种比较简单的方式,其实的任何组件的整合都有不少于两种的配置方式,下面来介绍下配置类如何配置。

MybatisAutoConfiguration自动配置类有如下一断代码:

@Bean  @ConditionalOnMissingBean  public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {}

@ConditionalOnMissingBean和@Bean真是老搭档了,意味着我们又可以覆盖,只需要在IOC容器中注入SqlSessionFactory(Mybatis六剑客之一生产者)。

在自定义配置类中注入即可,如下:

    @Bean("sqlSessionFactory1")    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();        sqlSessionFactoryBean.setDataSource(dataSource);        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper*.xml"));        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();        // 自动将数据库中的下划线转换为驼峰格式        configuration.setMapUnderscoreToCamelCase(true);        configuration.setDefaultFetchSize(100);        configuration.setDefaultStatementTimeout(30);        sqlSessionFactoryBean.setConfiguration(configuration);        return sqlSessionFactoryBean.getObject();    }

以上介绍了配置Mybatis的两种方式,其实在大多数场景中使用第一种已经够用了,至于为什么介绍第二种呢?当然是为了多数据源的整合而做准备了。

”在MybatisAutoConfiguration中有一行很重要的代码,如下:

@ConditionalOnSingleCandidate(DataSource.class)

@ConditionalOnSingleCandidate这个注解的意思是当IOC容器中只有一个候选Bean的实例才会生效。

这行代码标注在Mybatis的自动配置类中有何含义呢?下面介绍,哈哈哈~

多数据源如何整合?

上文留下的问题:为什么的Mybatis自动配置上标注如下一行代码:

@ConditionalOnSingleCandidate(DataSource.class)

以上这行代码的言外之意:当IOC容器中只有一个数据源DataSource,这个自动配置类才会生效。

”哦?照这样搞,多数据源是不能用Mybatis吗?

可能大家会有一个误解,认为多数据源就是多个的DataSource并存的,当然这样说也不是不正确。

多数据源的情况下并不是多个数据源并存的,Spring提供了AbstractRoutingDataSource这样一个抽象类,使得能够在多数据源的情况下任意切换,相当于一个动态路由的作用,作者称之为动态数据源。因此Mybatis只需要配置这个动态数据源即可。

什么是动态数据源?

动态数据源简单的说就是能够自由切换的数据源,类似于一个动态路由的感觉,Spring 提供了一个抽象类AbstractRoutingDataSource,这个抽象类中哟一个属性,如下:

private Map<Object, Object> targetDataSources;

targetDataSources是一个Map结构,所有需要切换的数据源都存放在其中,根据指定的KEY进行切换。当然还有一个默认的数据源。

AbstractRoutingDataSource这个抽象类中有一个抽象方法需要子类实现,如下:

protected abstract Object determineCurrentLookupKey();

determineCurrentLookupKey()这个方法的返回值决定了需要切换的数据源的KEY,就是根据这个KEY从targetDataSources取值(数据源)。

数据源切换如何保证线程隔离?

数据源属于一个公共的资源,在多线程的情况下如何保证线程隔离呢?不能我这边切换了影响其他线程的执行。

说到线程隔离,自然会想到ThreadLocal了,将切换数据源的KEY(用于从targetDataSources中取值)存储在ThreadLocal中,执行结束之后清除即可。

”单独封装了一个DataSourceHolder,内部使用ThreadLocal隔离线程,代码如下:

public class DataSourceHolder {    //线程  本地环境    private static final ThreadLocal<String> dataSources = new InheritableThreadLocal();    //设置数据源    public static void setDataSource(String datasource) {        dataSources.set(datasource);    }    //获取数据源    public static String getDataSource() {        return dataSources.get();    }    //清除数据源    public static void clearDataSource() {        dataSources.remove();    }}

如何构造一个动态数据源?

上文说过只需继承一个抽象类AbstractRoutingDataSource,重写其中的一个方法determineCurrentLookupKey()即可。

代码如下:

public class DynamicDataSource extends AbstractRoutingDataSource {        @Override    protected Object determineCurrentLookupKey() {        //从ThreadLocal中取出KEY        return DataSourceHolder.getDataSource();    }        public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {        //默认的数据源,可以作为主数据源        super.setDefaultTargetDataSource(defaultTargetDataSource);        //目标数据源        super.setTargetDataSources(targetDataSources);        //执行afterPropertiesSet方法,完成属性的设置        super.afterPropertiesSet();    }}

上述代码很简单,分析如下:

  • 一个多参的构造方法,指定了默认的数据源和目标数据源。

  • 重写determineCurrentLookupKey()方法,返回数据源对应的KEY,这里是直接从ThreadLocal中取值,就是上文封装的DataSourceHolder。

定义一个注解

为了操作方便且低耦合,不能每次需要切换的数据源的时候都要手动调一下接口吧,可以定义一个切换数据源的注解,如下:

@Target(value = ElementType.METHOD)@Retention(value = RetentionPolicy.RUNTIME)@Documentedpublic @interface SwitchSource {        String DEFAULT_NAME = "hisDataSource";        String value() default DEFAULT_NAME;}

注解中只有一个value属性,指定了需要切换数据源的KEY。

有注解还不行,当然还要有切面,代码如下:

@Aspect//优先级要设置在事务切面执行之前@Order(1)@Component@Slf4jpublic class DataSourceAspect {    @Pointcut("@annotation(SwitchSource)")    public void pointcut() {    }        @Before(value = "pointcut()")    public void beforeOpt(JoinPoint joinPoint) {                Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();        SwitchSource switchSource = method.getAnnotation(SwitchSource.class);        log.info("[Switch DataSource]:" + switchSource.value());        DataSourceHolder.setDataSource(switchSource.value());    }        @After(value = "pointcut()")    public void afterOpt() {        DataSourceHolder.clearDataSource();        log.info("[Switch Default DataSource]");    }}

这个ASPECT很容易理解,beforeOpt()在方法之前执行,取值@SwitchSource中value属性设置到ThreadLocal中;afterOpt()方法在方法执行之后执行,清除掉ThreadLocal中的KEY,保证了如果不切换数据源,则用默认的数据源。

如何与Mybatis整合?

单一数据源与Mybatis整合上文已经详细讲解了,数据源DataSource作为参数构建了SqlSessionFactory,同样的思想,只需要把这个数据源换成动态数据源即可。注入的代码如下:

    @Primary    @Bean("sqlSessionFactory2")    public SqlSessionFactory sqlSessionFactoryBean(DynamicDataSource dynamicDataSource) throws Exception {        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();        sqlSessionFactoryBean.setDataSource(dynamicDataSource);        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper*.xml"));        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();        configuration.setMapUnderscoreToCamelCase(true);        configuration.setDefaultFetchSize(100);        configuration.setDefaultStatementTimeout(30);        sqlSessionFactoryBean.setConfiguration(configuration);        return sqlSessionFactoryBean.getObject();    }

与Mybatis整合很简单,只需要把数据源替换成自定义的动态数据源DynamicDataSource。

”那么动态数据源如何注入到IOC容器中呢?看上文自定义的DynamicDataSource构造方法,肯定需要两个数据源了,因此必须先注入两个或者多个数据源到IOC容器中,如下:

    @ConfigurationProperties(prefix = "spring.datasource")    @Bean("dataSource")    public DataSource dataSource(){        return new DruidDataSource();    }        @Bean(name = SwitchSource.DEFAULT_NAME)    @ConfigurationProperties(prefix = "spring.datasource.his")    public DataSource hisDataSource() {        return DataSourceBuilder.create().build();    }

以上构建的两个数据源,一个是默认的数据源,一个是需要切换到的数据源(targetDataSources),这样就组成了动态数据源了。数据源的一些信息,比如url,username需要自己在全局配置文件中根据指定的前缀配置即可,代码不再贴出。

动态数据源的注入代码如下:

    @Primary    @Bean("sqlSessionFactory2")    public SqlSessionFactory sqlSessionFactoryBean(DynamicDataSource dynamicDataSource) throws Exception {        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();        sqlSessionFactoryBean.setDataSource(dynamicDataSource);        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();        configuration.setMapUnderscoreToCamelCase(true);        configuration.setDefaultFetchSize(100);        configuration.setDefaultStatementTimeout(30);        sqlSessionFactoryBean.setConfiguration(configuration);        return sqlSessionFactoryBean.getObject();    }

这里还有一个问题:IOC中存在多个数据源了,那么事务管理器怎么办呢?它也懵逼了,到底选择哪个数据源呢?因此事务管理器肯定还是要重新配置的。

”事务管理器此时管理的数据源将是动态数据源DynamicDataSource,配置如下:

    @Primary    @Bean(value = "transactionManager2")    public PlatformTransactionManager annotationDrivenTransactionManager(DynamicDataSource dataSource) {        return new DataSourceTransactionManager(dataSource);    }

至此,Mybatis与多数据源的整合就完成了。

演示

使用也是很简单,在需要切换数据源的方法上方标注@SwitchSource切换到指定的数据源即可,如下:

//不开启事务    @Transactional(propagation = Propagation.NOT_SUPPORTED)    //切换到HIS的数据源    @SwitchSource    @Override    public List<DeptInfo> list() {        return hisDeptInfoMapper.listDept();    }

这样只要执行到这方法将会切换到HIS的数据源,方法执行结束之后将会清除,执行默认的数据源。

到此,相信大家对“Spring Boot怎么整合多数据源”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Spring Boot怎么整合多数据源

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Spring Boot怎么整合多数据源

本篇内容主要讲解“Spring Boot怎么整合多数据源”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring Boot怎么整合多数据源”吧!前言:什么是多数据源?最常见的单一应用中最多涉及
2023-06-30

详解Spring Boot整合Mybatis实现 Druid多数据源配置

一、多数据源的应用场景目前,业界流行的数据操作框架是 Mybatis,那 Druid 是什么呢?Druid 是 Java 的数据库连接池组件。Druid 能够提供强大的监控和扩展功能。比如可以监控 SQL ,在监控业务可以查询慢查询 SQL
2023-05-31

spring boot怎么整合activiti

这篇文章主要介绍了spring boot怎么整合activiti的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇spring boot怎么整合activiti文章都会有所收获,下面我们一起来看看吧。spring
2023-06-29

Spring Boot怎么整合Kafka

这篇文章主要介绍了Spring Boot怎么整合Kafka的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Spring Boot怎么整合Kafka文章都会有所收获,下面我们一起来看看吧。步骤一:添加依赖项在 po
2023-07-05

Spring Boot中怎么整合elasticsearch

今天小编给大家分享一下Spring Boot中怎么整合elasticsearch的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧
2023-06-05

javaweb怎么整合多数据源搜索

要实现JavaWeb中多数据源的搜索,可以按照以下步骤进行整合:1. 配置多个数据源:在application.properties或者application.yml文件中配置多个数据源的连接信息,包括数据库驱动、URL、用户名和密码等。2
2023-09-21

多数据源怎么利用spring boot进行配置

本篇文章给大家分享的是有关多数据源怎么利用spring boot进行配置,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。多数据源配置创建一个Spring配置类,定义两个DataS
2023-05-31

SpringBoot怎么整合Druid数据源

本篇内容主要讲解“SpringBoot怎么整合Druid数据源”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringBoot怎么整合Druid数据源”吧! SprintBoot 默认使用的是
2023-07-02

Springboot多数据源配置之怎么整合dynamic-datasource

本篇内容介绍了“Springboot多数据源配置之怎么整合dynamic-datasource”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
2023-07-05

Spring Boot配置多数据源的四种方式

1、导读 在日常开发中我们都是以单个数据库进行开发,在小型项目中是完全能够满足需求的。 但是,当我们牵扯到像淘宝、京东这样的大型项目的时候,单个数据库就难以承受用户的CRUD操作。 那么此时,我们就需要使用多个数据源进行读写分离的操作,这种
2023-08-20

使用Spring boot怎么对Mybatis进行整合

这篇文章将为大家详细讲解有关使用Spring boot怎么对Mybatis进行整合,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1、文件结构DataBaseConfiguration.Jav
2023-05-31

Spring Boot怎么利用XML方式整合MyBatis

本篇内容介绍了“Spring Boot怎么利用XML方式整合MyBatis”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、前言下图是整个整
2023-06-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录