【SpringBoot整合系列】SpringBoot配置多数据源

目录

  • 背景
    • 技术选型
    • 配置多数据源思路(以两个为例)
    • 代码实现
      • 1.导入依赖
      • 2.各自的配置
    • 3.各自的dataSource
      • news数据库的
      • smbms数据库的
      • 注意:@Primary注解
    • 4.各自的SqlSessionFactory等
      • news数据库的
      • smbms数据库的
    • 5.去掉启动类头上的@MapperScan
    • 6.各自的mapper接口
    • 7.各自的mapper.xml
    • 8.测试

背景

  • 在单数据源的情况下,Spring Boot的配置非常简单,只需要在application.properties文件中配置连接参数即可。
  • 但是往往随着业务量发展,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源

技术选型

  • SpringBoot2.3.12
  • jdk1.8
  • mysql5.7
  • 持久层框架mybatis

配置多数据源思路(以两个为例)

  1. 要执行两个数据库的操作,就需要有两个数据库配置
  2. 有两个数据库配置那就要两个SqlSessionBuilder来创建SqlSessionFactory
  3. 有两个SqlSessionFactory就能创建两个数据库自己的sqlSession
  4. 然后就能执行不同数据库的操作了
  5. 现在用的都是数据库连接池,需要创建dataSource,因此,按照上面的思路,也需要有各自数据库的dataSource
  6. 用各自的dataSource创建各自的SqlSessionFactory
  7. 继而创建各自的SqlSessionTemplate
  8. 当然,事务管理器也应该是用各自的dataSource来创建
  9. 那么,各自的SqlSessionFactory就要扫描各自的mapper层,因此就需要有各自的mapper包
  10. 至于各自的mapper.xml可以放在一起,也可以不放在一起,因为mapper.xml中的namespace是根据包名来映射的

代码实现

1.导入依赖

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
        <!-- 阿里数据库连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.9</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.1</version>
        </dependency>

2.各自的配置

server:
  port: 8888

logging:
  level:
      org.springframework.web: debug
      com.kgc.mapper: debug
spring:
  datasource:
    smbms:
      driverClassName: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/smbms?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
    news:
      driverClassName: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/chinanewsdb?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
      username: root
      password: 123456

mybatis:
  mapper-locations: classpath:mybatis/mapper/*.xml
  type-aliases-package: com.kgc.pojo
  news:
    mapper-locations: classpath:mybatis/newsmapper/*.xml
#  configuration:
#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

在这里插入图片描述

3.各自的dataSource

news数据库的

package com.kgc.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

/**
 * @author: zjl
 * @datetime: 2024/4/20
 * @desc:
 */
@Configuration
//@ConfigurationProperties(prefix = "spring.datasource.news")
public class NewsDataSourceConfig {
    @Value("${spring.datasource.news.driverClassName}")
    private String driverClassName;
    @Value("${spring.datasource.news.url}")
    private String url;
    @Value("${spring.datasource.news.username}")
    private String username;
    @Value("${spring.datasource.news.password}")
    private String password;

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

smbms数据库的

package com.kgc.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

/**
 * @author: zjl
 * @datetime: 2024/4/20
 * @desc:
 */
@Configuration
//@ConfigurationProperties(prefix = "spring.datasource.smbms")
public class SmbmsDataSourceConfig {
    @Value("${spring.datasource.smbms.driverClassName}")
    private String driverClassName;
    @Value("${spring.datasource.smbms.url}")
    private String url;
    @Value("${spring.datasource.smbms.username}")
    private String username;
    @Value("${spring.datasource.smbms.password}")
    private String password;

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

注意:@Primary注解

  • 其作用与功能,当有多个相同类型的bean时,使用@Primary来赋予bean更高的优先级。
  • 在这里,需要注册多个相同DataSource类型的bean,要有一个有更高的优先级,否则会报错

4.各自的SqlSessionFactory等

news数据库的

package com.kgc.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * @author: zjl
 * @datetime: 2024/4/20
 * @desc:
 */
@Configuration
@EnableTransactionManagement
@MapperScan(value = "com.kgc.news.mapper",sqlSessionFactoryRef = "newsSqlSessionFactory")
public class NewsSqlSessionFactoryConfiguratiion {
    @Resource(name = "newsDataSource")
    private DataSource newsDataSource;
    @Value("${mybatis.news.mapper-locations}")
    private String mapperLocations;
    @Bean("newsSqlSessionFactory")
    public SqlSessionFactory create() throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(newsDataSource);
        PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        bean.setMapperLocations(resourcePatternResolver.getResources(mapperLocations));
        return bean.getObject();
    }

    @Bean("newsSqlSessionTemplate")
    public SqlSessionTemplate createSqlSession(@Qualifier("newsSqlSessionFactory") SqlSessionFactory sqlSessionFactory){
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean("newsTransactionManager")
    public PlatformTransactionManager createTransactionManager(){
        return new DataSourceTransactionManager(newsDataSource);
    }
}

smbms数据库的

package com.kgc.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.io.IOException;

/**
 * @author: zjl
 * @datetime: 2024/4/20
 * @desc:
 */
@Configuration
@EnableTransactionManagement
@MapperScan(value = "com.kgc.mapper",sqlSessionFactoryRef = "smbmsSqlSessionFactory")
public class SmbmsSqlSessionFactoryConfiguratiion {
    @Resource(name = "smbmsDataSource")
    private DataSource smbmsDataSource;
    @Value("${mybatis.mapper-locations}")
    private String mapperLocations;
    @Bean("smbmsSqlSessionFactory")
    public SqlSessionFactory create() throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(smbmsDataSource);
        PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        bean.setMapperLocations(resourcePatternResolver.getResources(mapperLocations));
        return bean.getObject();
    }

    @Bean("smbmsSqlSessionTemplate")
    public SqlSessionTemplate createSqlSession(@Qualifier("smbmsSqlSessionFactory") SqlSessionFactory sqlSessionFactory){
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean("smbmsTransactionManager")
    public PlatformTransactionManager createTransactionManager(){
        return new DataSourceTransactionManager(smbmsDataSource);
    }
}

5.去掉启动类头上的@MapperScan

@SpringBootApplication
//@MapperScan(basePackages = {"com.kgc.mapper"})
public class BootdemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(BootdemoApplication.class, args);
    }
}

6.各自的mapper接口

在这里插入图片描述

public interface UserMapper {
    int selectCount();
}
public interface NewsMapper {
    int selectCount();
}

7.各自的mapper.xml

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kgc.mapper.UserMapper">
    <select id="selectCount" resultType="int">
        SELECT COUNT(1) FROM SMBMS_USER
    </select>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kgc.news.mapper.NewsMapper">
    <select id="selectCount" resultType="int">
        SELECT COUNT(1) FROM news_detail
    </select>
</mapper>

8.测试

service

@Service
public class UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private NewsMapper newsMapper;

    public Integer allCount(){
        return userMapper.selectCount() + newsMapper.selectCount();
    }
}

controller

@RestController
public class UserController {
    @Resource
    private UserService userService;

    @RequestMapping("/all")
    public Object all(){
        return userService.allCount();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/573107.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

防火墙分为哪三类以及他们的优缺点

1. 包过滤防火墙&#xff08;Packet Filtering Firewall&#xff09;2. 状态检查防火墙&#xff08;Stateful Inspection Firewall&#xff09;3. 应用层防火墙&#xff08;Application Layer Firewall&#xff09;零基础入门学习路线视频配套资料&国内外网安书籍、文档网络…

Spring Cloud Alibaba Sentinel 使用

初识Sentinel Sentinel是阿里巴巴开源的一款微服务流量控制组件。官网地址&#xff1a; home | Sentinel 需要了解的概念 簇点链路 在学习 Sentinel 的使用之前&#xff0c;我们有必要首先了解一下簇点链路。当请求进入微服务时&#xff0c;首先会访Controller、Service、Ma…

C++11可变模板参数

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

百面算法工程师 | 卷积基础知识——Convolution

目录 8.1 图像卷积过程 8.2 卷积层基本参数 8.3 卷积后图像的长和宽大小的计算方式 8.4 卷积神经网络中的权重共享 8.5 上采样中的反卷积 8.6 空洞卷积 8.7 深度可分离卷积 8.8 为什么可分离卷积中Depthwise卷积后还要进行pointwise卷积 8.9 分组卷积 Group Conv 8.1…

前端导入的方便方法

直接上代码&#xff1a; 利用input的导入功能 这是相应的处理方法 是不是很简单呢

《系统架构设计师教程(第2版)》第10章-软件架构的演化和维护-01-软件架构演化概述

文章目录 1. 演化的重要性2. 架构演化示例 教材中&#xff0c;本节名为&#xff1a;“软件架构演化和定义的关系” 1. 演化的重要性 演化目的&#xff1a;维持软件架构自身的有用性 为什么说&#xff0c;软件架构是演化来的&#xff0c;而不是设计来的&#xff1f; 软件架构的…

【Shell】循环结构——for和while循环实例

Shell可以重复地执行特定的指令&#xff0c;直到特定的条件被满足为止。这重复执行的一组指令就叫做循环 特点&#xff1a; 首先&#xff0c;循环条件中使用的变量必须是已初始化的&#xff0c;然后在循环中开始执行每次在循环开始时进行一次测试重复地执行一个代码块 循环实例…

SD-WAN怎样提高企业网络体验

随着数字化转型的加速&#xff0c;传统基于MPLS的专用网络因其高度的结构化和僵化性&#xff0c;已无法满足现代企业对于灵活性和成本效益的日益增长的需求。相比之下&#xff0c;SD-WAN作为一种创新的网络架构&#xff0c;正以其卓越的性能和灵活的管理方式&#xff0c;成为企…

服务于金融新核心系统 星辰天合与中电金信完成产品兼容认证

近日&#xff0c;北京星辰天合科技股份有限公司&#xff08;简称&#xff1a;XSKY星辰天合&#xff09;与中电金信软件有限公司&#xff08;简称&#xff1a;中电金信&#xff09;完成产品兼容性认证&#xff0c;星辰天合的企业级分布式统一数据平台 XEDP 符合金融级数字底座&q…

ECG-Emotion Recognition(情绪识别)-- 数据集介绍WESADDREAMER

1、WESAD数据集 下载链接&#xff1a;WESAD: Multimodal Dataset for Wearable Stress and Affect Detection | Ubiquitous Computing &#xff08;1&#xff09;基本介绍 WESAD是一个用于可穿戴压力和影响检测的新的公开数据集。该多模式数据集以实验室研究期间15名受试者的生…

学习JFinal

1.五个配置类 configConstants&#xff08;配置&#xff09;&#xff1a; configRoute&#xff08;路由&#xff09;&#xff1a; 2.Controller层&#xff08;控制器&#xff09; 访问流程&#xff1a; Action&#xff1a; getPara&#xff1a; 参数说明&#xff1a;第一个参…

13.Blender 界面介绍(下) 雕刻、纹理绘制及属性

界面介绍 1. 布局 物体的移动旋转和缩放等操作 2. 建模 里面就是有一些建模常用的功能 里面的功能对于做MMD来说不是必备的操作 3. 雕刻 使用里面的工具可以对物体本身进行修改 4. UV编辑 如果想要编辑UV贴图 将编辑模式改为纹理绘制 再点击右边的工具 如果进行编…

MySQL-----多表查询(一)

目录 一.多表关系&#xff1a; 1.1 一对多(多对一)&#xff1a; 1.2 多对多: 1.3 一对一: 二.多表查询概述&#xff1a; 三.连接查询&#xff1a; 3.1内连接&#xff1a; 3.2外连接&#xff1a; 3.3自连接查询&#xff1a; 3.4联合查询&#xff1a; 一.多表关系&…

告别单一密码,多因素身份认证带你进入安全新纪元!

文章目录 前言一、你知道什么&#xff1f;二、你拥有什么1.智能卡2.令牌 三、你是什么四、其他因素身份认证 前言 当我们探讨多因子/多因素身份认证时&#xff0c;我们可能会好奇这里的“因素”具体指的是什么&#xff1f;显然&#xff0c;用户名和密码是一种因素&#xff0c;…

iclientOpenlayer用uniapp开发移动端GIS应用设计及实现

GIS移动端应用是将地理信息系统&#xff08;GIS&#xff09;技术应用于移动设备&#xff08;如智能手机、平板电脑&#xff09;上&#xff0c;使用户能在户外或移动场景下访问、收集、分析和展示地理信息。以下是GIS移动端应用的一些关键特性和应用场景&#xff1a; 关键特性&…

淘宝新店没有流量和访客怎么办

淘宝新店没有流量和访客时&#xff0c;可以采取以下措施来提升店铺的流量和吸引更多的访客&#xff1a; 3an推客是给商家提供的营销工具&#xff0c;3an推客CPS推广模式由商家自主设置佣金比例&#xff0c;以及设置商品优惠券&#xff0c;激励推广者去帮助商家推广商品链接&…

c++初阶——类和对象(中)

大家好&#xff0c;我是小锋&#xff0c;我们今天继续来学习类和对象。 类的6个默认成员函数 我们想一想如果一个类什么都没有那它就是一个空类&#xff0c;但是空类真的什么都没有吗&#xff1f; 其实并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以…

C++ | Leetcode C++题解之第43题字符串相乘

题目&#xff1a; 题解&#xff1a; class Solution { public:string multiply(string num1, string num2) {if (num1 "0" || num2 "0") {return "0";}int m num1.size(), n num2.size();auto ansArr vector<int>(m n);for (int i …

比亚迪海洋网再添实力爆款,海豹06DM-i、OCEAN-M、海狮07EV登陆北京车展

4月25日&#xff0c;比亚迪海洋网携海豹06DM-i、OCEAN-M、海狮07EV一齐亮相北京车展&#xff0c;引发关注热潮。其中&#xff0c;海洋网全新中型轿车海豹06DM-i价格区间12万-15万元&#xff0c;将于今年二季度上市&#xff1b;行业首款两厢后驱纯电钢炮OCEAN-M价格区间15万-20万…

重发布的原理及其应用

重发布的作用&#xff1a; 在一个网络中&#xff0c;若运行多种路由协议或者相同协议的不同进程&#xff1b;因为协议之间不能直接沟通计算&#xff0c;进程之间也是独立进行转发和运算的&#xff0c;所以&#xff0c;需要使用重发布来实现路由的共享。 条件 &#xff1a; 1&am…