测开工具:spring boot 实现同步数据库表结构(持续更新)

news2024/11/18 13:40:32

一、使用场景

一个项目,有多套开发环境。有一套标准的数据库,不同的开发环境,有各自的一套数据库。

标准数据库的表结构经常发生变化,不同的开发环境中的数据库,需要与标准数据库的表结构保持一致。当标准数据库表结构发生变化时,其他开发环境的数据库需要进行表结构的同步,与标准数据库保持一致。

二、MySQL 索引

MySQL 索引:

是一个单独的、存储在 磁盘 上的 数据库结构 ,包含着对数据表里 所有记录的 引用指针。

  

MySQL中索引的存储类型有两种:

即 BTree 和 Hash。

索引是在存储引擎中实现的:

(MySQL 的存储引擎有:InnoDB、MyISAM、Memory、Heap)

  • InnoDB / MyISAM 只支持 BTree 索引
  • Memory / Heap 都支持 BTree 和 Hash 索引

2.1 MYSQL 索引 的分类


1、普通索引 和 唯一索引

普通索引:MySQL 中的基本索引类型,允许在定义索引的列中插入 重复值 和 空值

唯一索引:要求索引列的值必须 唯一,但允许 有空值

如果是组合索引,则列值的组合必须 唯一
主键索引是一种特殊的唯一索引,不允许 有空值


2、单列索引 和 组合索引

单列索引:一个索引只包含单个列,一个表可以有多个单列索引
组合索引:在表的 多个字段 组合上 创建的 索引
只有在查询条件中使用了这些字段的 左边字段 时,索引才会被使用(最左前缀原则)


3、全文索引

全文索引 的类型为 fulltext
在定义索引的 列上 支持值的全文查找,允许在这些索引列中插入 重复值 和 空值
全文索引 可以在 char、varchar 和 text 类型的 列 上创建


4、空间索引

空间索引 是对 空间数据类型 的字段 建立的索引

MySQL中的空间数据类型有4种,分别是 Geometry、Point、Linestring 和 Polygon

MySQL 使用 Spatial 关键字进行扩展,使得能够用创建正规索引类似的语法创建空间索引

创建空间索引的列,不允许为空值,且只能在 MyISAM 的表中创建。

5、前缀索引

在 char、varchar 和 text 类型的 列 上创建索引时,可以指定索引 列的长度

三、information_schema库

information_schema库 :

用于存储数据库元数据(关于数据的数据),例如数据库名、表名、列的数据类型、访问权限等。

1、当我们对比,2个数据库是否一样时,我们只需要对比这两个数据库名称是否一致就可以了。

2、当我们对比,2个表是否一致时,我们需要去

1、表里,所有的字段属性

2、表里,索引。

我们通过这两个条件,来判断表与表是否一致,具体哪里不一致。

表information_schema.COlUMNS 记录了,某个表中,所有字段的属性。

我们在information_schema.COlUMNS,中查看表Student中,所有字段的属性。

在information_schema.statistics 表中,可以查看某个表下所有的索引。

在information_schema.SCHEMATA表中,可以查看这个实例下,都存在哪些数据库。

select SCHEMA_NAME,DEFAULT_CHARACTER_SET_NAME from information_schema.SCHEMATA

这个命令,就是查看我们实例下,所有的数据库。其实就是相当于

show databases; 
 

在information_schema.tables表中,可以查看某个数据库下,都存在哪些表。

select TABLE_SCHEMA,TABLE_NAME,ENGINE from information_schema.tables where schema_name = #{dbName}

其实就相当于命令:

use chen;
show tables;
 

四、整体思路

如数据库A为标准数据库。数据库B为我们本地的数据库。当数据库A表结构发生变化时,数据库B的表结构需要与A保持一致。

4.1 同步规则

我们拿本地的库与标准库做比较,

1、同步库:

1.1 将标准库中存在的库,但是本地不存在的库,同步到本地

1.2 标准库与本地库,都存在的库,只需要同步库里的表就可以了

1.3 在标准库中不存在的库,但是本地有的库,这种情况我们不进行考虑

2、同步表:

2.1 将标准库中存在的表,但是本地不存在的库,同步到本地

2.2 将标准库与本地库同时存在的表,但是表的结构不一样,将标准库的表结构同步到本地

2.3 同一个表中,本地表比标准表多余的字段,我们不考虑。

4.2 同步库

举例:

标准数据库A

 这个数据库实例下,一共有9个库。其中有5个库:

"information_schema","performance_schema","sys","mysql","test"

属于系统自带的库,我们进行同步时,不需要进行同步。我们只同步除了这5个系统之外的所有库。

数据库的属性:

1、只有数据库的名称。

所以,在对比标准库与本地库时,只需要比较数据库的名称就可以了。

标准库中有的库名,本地库没有该库名,我们在本地新增该数据库。

标准库与本地库,同时存在的库名,我们需要去校验同步库里面的表。

4.3 同步表

1 将标准库中存在的表,但是本地不存在的库,同步到本地

2 将标准库与本地库同时存在的表,但是表的结构不一样,将标准库的表结构同步到本地

3 同一个表中,本地表比标准表多余的字段,我们不考虑。

判断表与表是否一致时,我们需要比较2个条件。

1、表里,所有的字段属性

2、表里,索引。

我们通过这两个条件,来判断表与表是否一致,具体哪里不一致。

4.3.1 字段的属性:

 查看表information_schema.COlUMNS

每个列,对应一条数据。

每个列数据,我们需要取哪些属性值?


    private String tableSchema;
    private String tableName;
    private String columnName;
    private String columnType;
    private String columnComment;
    private String dataType;
    private String columnDefault;
    private String isNullable;

 4.3.2 mysql索引

 在information_schema.statistics 表中,可以查看某个表下所有的索引。

一个索引,就是一条数据。一个索引,都有哪些属性值呢?

    private String tableSchema;
    private String tableName;
    private String indexName;
    private int seqInIndex;
    private String columnName;
    private int nonUnique;
    private String indexType;

注意:

索引不能进行修改,只能先删除,后增加。

4.4 整体思路

1、我们拿本地的库与标准库做比较

2、先同步库

2.1 找到库与库的区别,生成对应的sql

2.2 去执行同步sql

3、再同步表

3.1 找到表与表的区别,生成对应的sql

3.2  去执行同步sql

4.5 最终效果

我们使用spring boot最终提供三个接口。

/instance 接口,同步两个实例。

/db 接口,只同步相应的数据库

/table 接口,只同步指定的表

五、 技术点

1、区分表与表,哪里不一致。哪些字段是新增的,哪些字段是修改的。

对索引的判断,哪些索引是新增的。这里技术难度不大,但是琐碎。

2、对于数据库的连接,我们使用的是mybatis。不同的是,以往spring boot 应用mybatis

在项目配置文件application.yml中,配置数据库的连接信息。

但是我们本次数据库连接信息需要用户传入,就不能使用application.yml配置。

六、项目代码、 项目整体结构

七、 pom依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.chenshuia.study</groupId>
    <artifactId>mysql-sync</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mysql-sync</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.20</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>29.0-jre</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

八、 controller层

对外提供的三个同步接口。

/instance 接口,同步两个实例。

/db 接口,只同步相应的数据库

/table 接口,只同步指定的表

package com.chenshuia.study.mysqlsync.controller;

import com.chenshuia.study.mysqlsync.bean.DBSyncInfo;
import com.chenshuia.study.mysqlsync.bean.ResultMsg;
import com.chenshuia.study.mysqlsync.bean.SyncInfo;
import com.chenshuia.study.mysqlsync.bean.TableSyncInfo;
import com.chenshuia.study.mysqlsync.service.SyncService;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.Objects;

@RequestMapping("/sync")
@RestController
public class SyncController {

    @Autowired
    private SyncService syncService;

    // 同步实例
    @RequestMapping(value = "/instance",method = RequestMethod.POST)
    public ResultMsg sync(@RequestBody SyncInfo syncInfo){
        // 参数校验
        try {
            syncInfo.verify();
            syncService.syncInstance(syncInfo);
            return ResultMsg.success();
        } catch (Exception e){
            e.printStackTrace();
            return ResultMsg.fail(ResultMsg.FAILED_CODE,e.getMessage());
        }

    }

    // 同步库
    @RequestMapping(value = "/db",method = RequestMethod.POST)
    public ResultMsg sync(@RequestBody DBSyncInfo dbSyncInfo){
        try {
            dbSyncInfo.verify();
            syncService.syncDB(dbSyncInfo);
            return ResultMsg.success();

        } catch (Exception e){
            e.printStackTrace();
            return ResultMsg.fail(ResultMsg.FAILED_CODE,e.getMessage());
        }
        
    }

    // 同步表
    @RequestMapping(value = "/table",method = RequestMethod.POST)
    public ResultMsg sync(@RequestBody TableSyncInfo tableSyncInfo){
        try {
            // 校验参数
            tableSyncInfo.verify();
            // 调用业务,处理数据
            syncService.syncTable(tableSyncInfo);
            return ResultMsg.success();
        } catch (Exception e){
            e.printStackTrace();
            return ResultMsg.fail(ResultMsg.FAILED_CODE,e.getMessage());
        }

    }

}

1、三个接口,都是post方法

2、具体的同步方法,都在

    @Autowired
    private SyncService syncService;

通过spring注入

3、同步实例时,需要传入所有的信息。本地库与标准库的连接信息。

同步库,需要传入2个库的连接信息,与数据库的名称。

同步表,需要传入2个库的连接信息,与数据库的名称、表的名称。

4、我们在同步数据库之前,先对用户传参进行了一个校验。

九、 bean层

 bean层存放了整个项目,需要的所有实例。

9.1 返回结果的实例ResultMsg<T> 

定义了一个返回结果的实例,用到了范型。(没有什么逻辑)

package com.chenshuia.study.mysqlsync.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.omg.CORBA.PUBLIC_MEMBER;

@Data
@AllArgsConstructor
public class ResultMsg<T> {
    private String code;
    private String msg;
    private T data;

    public static final String SUCCESS_CODE = "200";
    public static final String FAILED_CODE = "999";
    public static final String SUCCESS_MSG = "success";
    public static final String FAILED_MSG = "failed";

    public ResultMsg(String code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public static <T> ResultMsg<T> success(T t){
        return new ResultMsg<>(SUCCESS_CODE,SUCCESS_MSG,t);
    }

    public static ResultMsg success(){
        return new ResultMsg<>(SUCCESS_CODE,SUCCESS_MSG);
    }

    public static ResultMsg fail(){
        return new ResultMsg<>(FAILED_CODE,FAILED_MSG);
    }

    public static ResultMsg fail(String code,String msg){
        return new ResultMsg<>(code,msg);
    }
}

9.2 数据库连接信息(用户传入信息)

一共有4个实体类。ConnectInfo、SyncInfo 

ConnectInfo

package com.chenshuia.study.mysqlsync.bean;

import com.chenshuia.study.mysqlsync.util.VerifyUtil;
import com.mysql.cj.jdbc.Driver;
import lombok.Data;

@Data
public class ConnectInfo {
    /*
    数据库链接信息
     */
    private String driver = Driver.class.getName();
    private String url ;
    private String userName ;
    private String password ;

    public void verify(){
        VerifyUtil.verifyString(url,userName,password,driver);
    }

}

SyncInfo 

package com.chenshuia.study.mysqlsync.bean;

import lombok.Data;

import java.util.Objects;

@Data
public class SyncInfo {
    /*
    进行同步的信息。2个数据库的链接方式,同步的库和表
     */

    private ConnectInfo src;
    private ConnectInfo dst;

    public void verify(){
        // 判断属性src与dst 是否为空
        Objects.requireNonNull(src);
        Objects.requireNonNull(dst);
        // 判断对象src的属性是否为空
        src.verify();
        dst.verify();
    }
}

 

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

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

相关文章

HNU编译原理实验一cminus_compiler-2022-fall

前言&#xff1a;实验不是很难&#xff0c;主要考察正则表达式部分 lab1实验报告实验要求 根据cminux-f的词法补全lexical_analyer.l文件&#xff0c;完成词法分析器&#xff0c;能够输出识别出的token&#xff0c;type ,line(刚出现的行数)&#xff0c;pos_start(该行开始位置…

[机缘参悟-95] :不同人生、社会问题的本质

事情的本质是物极必反&#xff08;轮回、周期&#xff09; 社会的本质是优胜劣汰&#xff08;迭代、发展&#xff09; 道德的本质是伦理秩序&#xff08;未定、秩序&#xff09; 战争的本质是资源占用&#xff08;弱肉、强食&#xff09; 商业的本质是价值交换 金钱的本质…

基于JAVA SpringBoot+ JWT+Redis的ERP系统,VUE+Element-UI 前后端分离的Saas平台

项目简介 简云Saas平台 基于SpringBoot2.2.0, Mybatis, JWT, Redis, VUEElement-UI 的前后端分离的Saas平台管理系统 在线报表开发 在线表单设计 工作流设计 自定义打印模板定义 **产品分二个版本: 开源版本(包含了系统基础架构在线表单设计). 此版本代码完全开源ERP版本…

Flink-基本的合流操作

文章目录1.基本的合流操作2.1联合&#xff08;Union&#xff09;2.2 连接&#xff08;Connect&#xff09;2.基于时间的合流——双流联结&#xff08;Join&#xff09;2.1 窗口联结&#xff08;Window Join&#xff09;2.2 间隔联结&#xff08;Interval Join&#xff09;2.3 窗…

《面向对象分析与设计》总结

面向对象的软件工程1 面向对象的演化1.1 生活中复杂系统的特点1.2 软件系统的复杂性1.2.1 复杂性的四个方面1.2.1.1 问题域的复杂性1.2.1.2 管理开发的困难性1.2.1.3 软件中的灵活性1.2.1.4 描述离散系统行为1.2.2 复杂系统的五个属性1.2.2.1 层次结构1.2.2.1.1 对象结构1.2.2.…

数据分析神器:数据自动录入并生成BI报表

做报表、分析数据、做汇报是许多打工人的日常&#xff0c;每天都要耗费不少的时间用Excel来整理、清洗数据和生成好看的报表。如果这些数据都是手动整理、复制粘贴的话&#xff0c;不仅费时费力&#xff0c;而且很容易出错。 在越来越多企业采用SaaS产品和不同数据应用的今天&…

来看一个vue-element-表单之登录页面,最后送上一个登录页面

vue-element 表单之登录页面使用 0. 先留下属性表格 表单验证&#xff1a;Form 组件提供了表单验证的功能&#xff0c;只需要通过 rules 属性传入约定的验证规则&#xff0c;并将 Form-Item 的 prop 属性设置为需校验的字段名即可。 1. 表单属性表(el-form) 2. 表单项属性表…

php工作流引擎再发新版本—Tpflow7.0重磅发布

2022年已接近尾声&#xff0c;又到了每年发布大版本的时候&#xff0c;Tpflow历经一个多月的意见征集及版本优化&#xff0c;从底层改进&#xff0c;从UI调整&#xff0c;增强了事件功能。 发布日期&#xff1a;2022年12月23日 发布版号&#xff1a;V7.0.0 Tpflow 工作流引擎…

短视频引流+私域流量沉淀,一个全新的短视频和链动模式结合方案

在微盟企微助手微盟智慧零售团队的协助下&#xff0c;今年7月底么么茶正式开始运营企微私域&#xff0c;截至当前&#xff0c;在短短3个月时间已成功沉淀7万私域客户&#xff0c;线上商城GMV超145万。 么么茶旅拍的核心流量来源自公域短视频平台&#xff0c;品牌基于服务覆盖下…

OB0206 obsidian 表格编辑插件:advanced Tables插件使用

序号解读&#xff1a; 01——软件基础使用、基础语法 02——插件使用 03——综合实战 0 写在前面 Ob社区插件汇总&#xff1a;Airtable - OB社区插件汇总 - Johnny整理 - 每周更新 - B站 Johnny学Explore the "OB社区插件汇总 - Johnny整理 - 每周更新 - B站 Johnny学&qu…

执行操作后的变量值,我的题解首次优于官方

2011. 执行操作后的变量值 难度简单46 存在一种仅支持 4 种操作和 1 个变量 X 的编程语言&#xff1a; X 和 X 使变量 X 的值 加 1--X 和 X-- 使变量 X 的值 减 1 最初&#xff0c;X 的值是 0 给你一个字符串数组 operations &#xff0c;这是由操作组成的一个列表&#xf…

求N阶矩阵的幂(一维,二维多种方法)

引用&#xff1a;对于矩阵的计算想必都是一件很头疼的事情吧&#xff0c;因为计算量是比较大&#xff0c;因为你要用前一个矩阵的行乘以后矩阵的列且对应相加才得到新矩阵的第一个元素&#xff0c;且两个矩阵可以相乘的条件也是前一个矩阵的列等于后一个矩阵的行&#xff0c;操…

Simulink代码生成: Switch模块及其代码

本文描述Switch模块的建模并研究生成的代码。 文章目录1 Simulink中的Switch模块2 Switch模块建模及代码生成3 Switch模块其他用法3.1 多重Switch3.2 通过标定量Switch4 总结1 Simulink中的Switch模块 在Simulink中Switch模块时非常常见的&#xff0c;通常用于根据一定地条件选…

Python学习笔记(十九)——Matplotlib入门上

目录 Matplotlib简介 导入matplotlib模块 图的参数说明 matplotlib图像组成部分介绍 matplotlib绘图步骤分析 matplotlib实现简单图像 matplotlib画布 画布-plt.figure() 实例 同一画布制作多张图像 创建多个子图 实例 plt.subplots 相关参数 调整subplot周围的间距…

使用HGS算法调整PD控制器增益的无人机动态性能数据——基于启发式的无人机路径跟踪优化(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

【Sentinel 预热加载】

系列文章目录 Sentinel 预热加载 目录 系列文章目录 前言 一、概念解释&#xff1f; 二、使用步骤 1.引入库 2.dashboard 配置 总结 前言 一、概念解释&#xff1f; Warm Up&#xff1a;根据coldFactor&#xff08;冷加载因子&#xff0c;默认3&#xff09;的值&#xff0c;从…

有了 HTTP,为什么还要 RPC?

RPC主要是基于TCP/IP协议的&#xff0c;而HTTP服务主要是基于HTTP协议的&#xff0c;我们都知道HTTP协议是在传输层协议TCP之上的&#xff0c;所以效率来看的话&#xff0c;RPC当然是要更胜一筹啦&#xff01;下面来具体说一说RPC服务和HTTP服务。 OSI网络七层模型 在说RPC和…

Android HIDL和hwservicemanager

HIDL软件包 HIDL 接口软件包位于 hardware/interfaces 或 vendor/ 目录下&#xff08;个别情况除外&#xff09;。顶层 hardware/interfaces 会直接映射到 android.hardware 软件包命名空间&#xff1b;版本是软件包&#xff08;而不是接口&#xff09;命名空间下的子目录。 h…

ALPHA项目的测试电机、性能信息和动态推力近似值数据库(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 按照电机试验的完整性&#xff0c;可以将电机试验分为型式试验、单项目或部分项目试验等&#xff1b;其中型式试验包括产品的性…

【深入浅出Spring原理及实战】「开发实战系列」SpringSecurity与JWT实现权限管控以及登录认证指南

SpringSecurity介绍 SpringSecurity是一个用于Java 企业级应用程序的安全框架&#xff0c;主要包含用户认证和用户授权两个方面&#xff0c;相比较Shiro而言&#xff0c;Security功能更加的强大&#xff0c;它可以很容易地扩展以满足更多安全控制方面的需求&#xff0c;但也相…