【SpringBoot】11 多数据源(MyBatis:dynamic-datasource)

news2024/11/28 11:45:18

介绍

多数据源:指的是一个单一应用程序中涉及了两个及以上的数据库,这种配置允许应用程序根据业务需求灵活地管理和操作不同的数据库。

需求

一个应用服务中,连接多个数据库,有本地的也有远程的,有MysQL、Oracle、PostgreSQL(按需配置,可以配置同样的数据源,也可以配置不用的数据源)。

依赖

pom.xml

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.5.1</version>
</dependency>

效果图

项目启动时,载入的三个数据源。
在这里插入图片描述在这里插入图片描述
用户接口(wx数据库)
在这里插入图片描述
角色接口(alipay数据库)
在这里插入图片描述
权限接口(oct数据库)
在这里插入图片描述

代码实现

配置文件中连接了三个数据库,wx数据库是MySQL,alipay数据库是Oracle,oct数据库是PostgreSQL。wx数据库是在本地,alipay数据库和oct数据库是在远程,可以按需配置。
注:项目启动程序就会去创建与所有配置数据库之间的连接,如果连不上则会启动失败。

配置

application.yml

server:
  port: 8888

spring:
  application:
    name: system
  thymeleaf:
    prefix: classpath:/templates/ #前缀,默认为classpath:/templates/
    suffix: .html #后缀,默认为.html
#  单个数据库
#  datasource:
#    driver-class-name: com.mysql.cj.jdbc.Driver
#    url: jdbc:mysql://localhost:3306/system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
#    username: root
#    password: root
# 多个数据库
  datasource:
    dynamic:
#      primary: master #默认主库
      strict: true
      datasource:
        wx: #MySQL
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://localhost:3306/wx?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
          username: root
          password: root
        alipay: #Oracle
          driver-class-name: oracle.jdbc.OracleDriver
          url: jdbc:oracle:thin:@remote:1521:sid #remote是对应机器服务器的远程地址,sid是具体的数据库实例
#          driver-class-name: com.mysql.jdbc.Driver
#          url: jdbc:mysql://localhost:3306/alipay?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
          username: root
          password: root
        oct: #PostgreSQL
          driver-class-name: org.postgresql.Driver
          url: jdbc:postgresql://remote:5432/postgres #remote是对应机器服务器的远程地址
#          driver-class-name: com.mysql.jdbc.Driver
#          url: jdbc:mysql://localhost:3306/oct?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
          username: root
          password: root

  mail:
    #    host: smtp.163.com
    host: smtp.qq.com
    port: 465 #587
    #    username: xxx@163.com
    username: xxx@qq.com
    password: xxx #授权码
    default-encoding: UTF-8
    properties:
      mail:
        debug: true
        smtp:
          socketFactory:
            class: javax.net.ssl.SSLSocketFactory
          ssl:
            enable: true

schedule:
  cron:  0/5 * * * * ?  #5s执行一次
  wxFlag: true
  alipayFlag: false
  octFlag: false

logging:
  config: classpath:log4j2.yml
  level:
    com.lm.system.mapper: debug

代码

所有的User相关的方法默认读取wx的MySQL数据库,只要在类上加上 @DS(“wx”) 注解。如果是接口中多个方法用到多个不同的数据源时,可在方法上加@DS(“wx”)注解,该注解是按就近原则进行加载。

User(wxDB)

UserMapper.java

@DS("wx")
public interface UserMapper {}

Role(alipayDB)

Role.java

package com.lm.system.common;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

/**
 * @author DUHAOLIN
 * @date 2024/8/21
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Role {

    @TableId(value = "role_id", type = IdType.INPUT)
    private Integer roleId; //自增长
    private String roleName;
    private String description;
    private Integer status; //可用状态,0不可用,1可用
    private Date createTime;
    private Date updateTime;

}

RoleMapper.java

package com.lm.system.mapper;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.lm.system.common.Role;

import java.util.List;

/**
 * @author DUHAOLIN
 * @date 2024/8/21
 */
@DS("alipay")
public interface RoleMapper {

    List<Role> queryRoles();

}

RoleMapper.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.lm.system.mapper.RoleMapper">

    <resultMap id="beans" type="com.lm.system.common.Role">
        <id property="roleId" column="role_id" jdbcType="INTEGER" />
        <result property="roleName" column="role_name" jdbcType="VARCHAR" />
        <result property="status" column="status" jdbcType="INTEGER" />
        <result property="description" column="description" jdbcType="VARCHAR" />
        <result property="createTime" column="create_time" jdbcType="DATE" />
        <result property="updateTime" column="update_time" jdbcType="DATE" />
    </resultMap>

    <select id="queryRoles" resultMap="beans">
        SELECT * FROM T_ROLE
    </select>


</mapper>

RoleController.java

package com.lm.system.controller;

import com.lm.system.common.ResultBody;
import com.lm.system.common.Role;
import com.lm.system.mapper.RoleMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author DUHAOLIN
 * @date 2024/8/21
 */
@RestController
@Api(tags = "角色接口")
@RequestMapping("role")
public class RoleController {

    @Resource
    private RoleMapper roleMapper;

    @GetMapping("query")
    @ApiOperation("获取角色信息")
    public String queryRoles() {
        List<Role> roles = roleMapper.queryRoles();
        return ResultBody
                .build(roles == null ? HttpStatus.NO_CONTENT : HttpStatus.OK)
                .setData(roles)
                .setCount(roles == null ? 0 : 1)
                .getReturn();
    }

}

Permission(octDB)

Permission.java

package com.lm.system.common;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

/**
 * @author DUHAOLIN
 * @date 2024/8/21
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Permission {

    @TableId(value = "permission_id", type = IdType.INPUT)
    private Integer permissionId; //自增长
    private String permissionName;
    private String description;
    private Date createTime;
    private Date updateTime;

}

PermissionMapper.java

package com.lm.system.mapper;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.lm.system.common.Permission;

import java.util.List;

/**
 * @author DUHAOLIN
 * @date 2024/8/21
 */
public interface PermissionMapper {

    @DS("oct")
    List<Permission> queryPermissions();

}

Permission.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.lm.system.mapper.PermissionMapper">

    <resultMap id="beans" type="com.lm.system.common.Permission">
        <id property="permissionId" column="permission_id" jdbcType="INTEGER" />
        <result property="permissionName" column="permission_name" jdbcType="VARCHAR" />
        <result property="description" column="description" jdbcType="VARCHAR" />
        <result property="createTime" column="create_time" jdbcType="DATE" />
        <result property="updateTime" column="update_time" jdbcType="DATE" />
    </resultMap>

    <select id="queryPermissions" resultMap="beans">
        SELECT * FROM T_PERMISSION
    </select>

</mapper>

PermissionController.java

package com.lm.system.controller;

import com.lm.system.common.Permission;
import com.lm.system.common.ResultBody;
import com.lm.system.mapper.PermissionMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author DUHAOLIN
 * @date 2024/8/21
 */
@RestController
@Api(tags = "权限接口")
@RequestMapping("permission")
public class PermissionController {

    @Resource
    private PermissionMapper permissionMapper;

    @GetMapping("query")
    @ApiOperation("获取权限信息")
    public String queryPermission() {
        List<Permission> permissions = permissionMapper.queryPermissions();
        return ResultBody
                .build(permissions == null ? HttpStatus.NO_CONTENT : HttpStatus.OK)
                .setData(permissions)
                .setCount(permissions == null ? 0 : 1)
                .getReturn();
    }

}

SQL

t_user.sql

/*
 Navicat Premium Data Transfer

 Source Server         : localhost
 Source Server Type    : MySQL
 Source Server Version : 50734
 Source Host           : localhost:3306
 Source Schema         : wx

 Target Server Type    : MySQL
 Target Server Version : 50734
 File Encoding         : 65001

 Date: 21/08/2024 16:49:21
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `age` int(11) NULL DEFAULT NULL,
  `gender` varchar(2) NOT NULL COMMENT ,
  `deleted` tinyint(1) NOT NULL COMMENT '0未删除,1已删除',
  `create_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
  `update_time` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES (1, 'Tom', 18, '男', 0, '2024-08-21 16:47:45', '2024-08-21 16:47:45');
INSERT INTO `t_user` VALUES (2, 'Joe', 20, '女', 0, '2024-08-21 16:47:58', '2024-08-21 16:47:58');
INSERT INTO `t_user` VALUES (3, 'Jim', 33, '女', 0, '2024-08-21 16:48:12', '2024-08-21 16:48:12');

SET FOREIGN_KEY_CHECKS = 1;

t_role.sql

--------------------------------------------------------
--  文件已创建 - 星期三-八月-21-2024   
--------------------------------------------------------
--------------------------------------------------------
--  DDL for Table T_ROLE
--------------------------------------------------------

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for T_ROLE
-- ----------------------------
DROP TABLE IF EXISTS `T_ROLE`;
CREATE TABLE `T_ROLE`  (
  `ROLE_ID` int(11) NOT NULL AUTO_INCREMENT,
  `ROLE_NAME` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `DESCRIPTION` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `STATUS` tinyint(1) NOT NULL COMMENT '可用状态,0不可用,1可用',
  `CREATE_TIME` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
  `UPDATE_TIME` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
  PRIMARY KEY (`ROLE_ID`) USING BTREE
);

-- ----------------------------
-- Records of T_ROLE
-- ----------------------------
INSERT INTO `T_ROLE` VALUES (-1, '管理员', '拥有所有权限', 1, '2024-08-21 17:04:01', '2024-08-21 17:04:01');
INSERT INTO `T_ROLE` VALUES (1, '财务', '拥有查看和操作权限', 1, '2024-08-21 17:04:14', '2024-08-21 17:04:14');
INSERT INTO `T_ROLE` VALUES (2, '观察员', '拥有查看的账号', 1, '2024-08-21 17:05:19', '2024-08-21 17:05:19');

SET FOREIGN_KEY_CHECKS = 1;

t_permission.sql

/*
 Navicat Premium Data Transfer

 Source Server         : oct
 Source Server Type    : PostgreSQL
 Source Server Version : 120001
 Source Host           : remote:port
 Source Catalog        : oct
 Source Schema         : public

 Target Server Type    : PostgreSQL
 Target Server Version : 120001
 File Encoding         : 65001

 Date: 21/08/2024 16:53:21
*/


-- ----------------------------
-- Table structure for t_permission
-- ----------------------------
DROP TABLE IF EXISTS "public"."t_permission";
CREATE TABLE "public"."t_permission" (
  "permission_id" varchar(30) COLLATE "pg_catalog"."default" NOT NULL,
  "permission_name" varchar(30) COLLATE "pg_catalog"."default" NOT NULL,
  "description" varchar(150) COLLATE "pg_catalog"."default",
  "create_time" timestamp(0) COLLATE "pg_catalog"."default" NOT NULL,
  "update_time" timestamp(0) COLLATE "pg_catalog"."default" NOT NULL
)
;

-- ----------------------------
-- Records of oct
-- ----------------------------
INSERT INTO "public"."t_permission" VALUES (1, '用户管理', '管理用户账号', '2024-08-22 09:35:18', '2024-08-22 09:35:18');
INSERT INTO "public"."t_permission" VALUES (2, '角色管理', '管理用户角色', '2024-08-22 09:35:50',    '2024-08-22 09:35:50');
INSERT INTO "public"."t_permission" VALUES (3, '权限管理', '管理角色权限', '2024-08-22 09:36:05',    '2024-08-22 09:36:05');

-- ----------------------------
-- Primary Key structure for table t_permission
-- ----------------------------
ALTER TABLE "public"."t_permission" ADD CONSTRAINT "t_permission_pk" PRIMARY KEY ("id", "option");

项目目录结构图

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法训练营day51:图论02:99. 岛屿数量;100. 岛屿的最大面积

99. 岛屿数量 卡码网题目链接&#xff08;ACM模式&#xff09;(opens new window) 题目描述&#xff1a; 给定一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的矩阵&#xff0c;你需要计算岛屿的数量。岛屿由水平方向或垂直方向上相邻的陆地连接而…

PHP农场扶农系统智慧认养智慧乡村系统农场系统小程序源码

&#x1f331;科技赋能田园梦 —— 探索“农场扶农系统”与“智慧认养智慧乡村”新篇章&#x1f680; &#x1f308;【开篇&#xff1a;田园新风尚&#xff0c;科技引领未来】 在快节奏的都市生活中&#xff0c;你是否曾梦想过拥有一片属于自己的绿色天地&#xff1f;现在&am…

大一新生看过来,【入学证件照】这样拍才可以千万不要拍错了

大一新生在拍摄证件照时&#xff0c;确实需要注意一些关键点&#xff0c;以确保照片符合规定并能成功使用。‌不会的可以多看看我首页说明&#xff0c;VX小城续&#xff1a;桃子证件照&#xff0c;帮你搞定大学四年所以的照片可以打印邮寄 首先&#xff0c;重要的是要注意以下几…

通信总线-串口/IIC/SPI

基本概念 1.串行&#xff1a;只有一个数据线&#xff0c;bit&#xff08;位&#xff09;一个一个传输&#xff08;本质传输的是电信号&#xff0c;高低电平代表0或1&#xff09; 更常用&#xff08;UART&#xff0c;IIC&#xff0c;SPI&#xff09; 2.并行&#xff1a;多个…

企业文件防泄密怎么做?10款透明加密软件排行榜

在信息时代&#xff0c;企业的核心竞争力往往体现在其拥有的知识和信息上&#xff0c;而企业文件的安全性直接关系到这些信息的保护。文件防泄密已成为企业管理中的重要议题&#xff0c;透明加密技术因其无缝集成和高效保护的特性&#xff0c;成为企业防泄密的首选方案。2024年…

RabbitMQ与ElasticSearch面试

目录 RabbitMQ 1、你们项目中哪里用到了RabbitMQ 2、为什么会选择使用RabbitMQ 3、使用RabbitMQ如何保证消息不丢失 4、消息的重复消费问题如何解决的 5、如何解决消息堆积在MQ的问题 6、RabbitMQ如何保证消费的顺序性 7、RabbitMQ的延迟队列有了解过嘛 8、RabbitMQ如…

<数据集>流水线物件识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;8643张 标注数量(xml文件个数)&#xff1a;8643 标注数量(txt文件个数)&#xff1a;8643 标注类别数&#xff1a;26 标注类别名称&#xff1a;[Crankshaft, Centrifugal_body, Washer_container, Circlip_containe…

FTP协议-匿名用户登录 从0到1

前言 日常大家可能接触web漏洞比较多而对其他端口及协议不那么了解&#xff0c;其实其他协议漏洞在渗透中也同样重要只是平时可能接触得不多。本文将介绍FTP协议、FTP匿名用户登录及其具体流程分析和自动化利用demo。 FTP简介 FTP是File Transfer Protocol&#xff08;文件传…

利用Aspose.BarCode 在 C# 中创建微型二维码

Aspose.BarCode提供多种编程语言的 API&#xff0c;例如Java、Python、C等。它提供了强大的解决方案&#xff0c;可以通过编程创建和处理条形码和二维码&#xff0c;我们将实现如何使用Aspose.BarCode for .NET在 C# 中创建微型二维码。接下来&#xff0c;我们还将演示如何以编…

软件测试工程师是做什么的?

软件测试工程师扮演着软件开发过程中的关键角色&#xff0c;他们的主要职责是对软件进行全面的测试&#xff0c;确保其质量和稳定性。 随着软件行业的迅猛发展&#xff0c;对这类专业人才的需求也在不断增长。 本文将深入探讨软件测试工程师的职责及其所需的技能。 一、软件测…

新技术能够区分真实照片和 AI 伪造图片,但为何平台没有使用?|TodayAI

随着生成式 AI 图像工具的快速发展&#xff0c;网络上越来越多的图像真假难辨。尽管已有技术能够区分真实照片和 AI 伪造图片&#xff0c;但大多数在线平台尚未充分利用这一技术。随着美国总统大选临近&#xff0c;网络上充斥着关于候选人唐纳德特朗普和卡玛拉哈里斯的各种照片…

组合模式 详解

组合模式 简介: 将对象组合成树形结构以表示"部分-整体"的层次结构, 使得用户对单个对象和组合对象的使用具有一致性. 组合模式也是一种结构类型的模式.看简介比较容易理解, 毕竟树形结构是数据结构必修的, 我们仍然举个例子方便理解 以公司的组织架构为例 公司 - …

Web大学生网页作业成品——明星EXO介绍网页设计与实现(HTML+CSS)(10个页面)(TABLE布局)

&#x1f389;&#x1f389;&#x1f389; 常见网页设计作业题材有**汽车、环保、明星、文化、国家、抗疫、景点、人物、体育、植物、公益、图书、节日、游戏、商城、旅游、家乡、学校、电影、动漫、非遗、动物、个人、企业、美食、婚纱、其他**等网页设计题目, 可满足大学生网…

LED 数码显示管的结构

LED 数码显示管是一种常用的字符显示器件,能与 CMOS、TTL 等集成电路直接配合,作静态、动态扫描显示之用。图12-33(a)是LED数码显示管的实物图&#xff0c;图 12-33(b)是LED数码显示管的内部结构。它实际上是由8个发光二极管构成的&#xff0c;其中7个发光二极管排列成“8”字形…

【线性表】内容总结

1.单链表&#xff0c;循环链表&#xff0c;双向链表的循环效率 2.顺序表和链表的比较 1.什么是存储密度 1.定义&#xff1a; 存储密度是指结点数据本身所占的存储量和整个结点结构中所占的存储量 之比&#xff0c;即: 2.实例 比如在32位系统上&#xff0c;一个12字节的结…

保姆级Python与PyCharm安装教程

本文演示所用的所用的所有工具包都已经打包好了&#xff0c;【点击这里】即可获得 一、简介 Python是一种广泛使用的高级编程语言&#xff0c;因其简洁的语法和丰富的库支持&#xff0c;在数据科学、Web开发、人工智能等领域广受欢迎。PyCharm是由JetBrains开发的一款针对Pyt…

一篇文章带你了解归并排序-分治法

文章目录 两个有序数组排序一个局部有序数组排序分治法归并排序 两个有序数组排序 先来一个场景假设&#xff0c;先有两个有序数组{1,3,5,9}、{2,4,6,8}&#xff0c;要求合并成一个有序数组。 我们先上一段简单的处理代码 public static int[] merge(int[] leftArr, int[] righ…

Redis后台线程之非阻塞删除

当Redis执行删除命令的时候&#xff0c;如果被删除的对象是列表、集合、散列类型&#xff0c;因为这些数据类型包含的元素存放在不同的内存块中&#xff0c;redis需要遍历所有元素来释放其对应的内存块空间&#xff0c;这个耗时操作可能导致redis阻塞&#xff0c;redis4提供的U…

[数据集][目标检测]agvs仓储机器人检测数据集VOC+YOLO格式967张3类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;967 标注数量(xml文件个数)&#xff1a;967 标注数量(txt文件个数)&#xff1a;967 标注类别…

API接口安全101:基础概念与最佳实践

文章目录 API定义协议架构风格描述语言 Webservicewsdl介绍复现 SOAPswagger介绍指纹查找利用存在目录复现 HTTPWebpack介绍复现 在当今数字化时代,API接口已成为现代软件架构中不可或缺的组成部分。它们连接着各种应用程序和服务,促进了数据交换和功能集成。然而,随着API的普及…