java实现mysql两个数据库对比表结构是否一致

news2024/12/26 23:25:06

【使用场景】

本地开发完后,增加或者删除了字段,或者修改了字段属性。

如何判定现场环境和本地环境的数据表结构一致性? 肉眼看的话,实在是一个大的工作量,所以开发了此工具。

【类存放路径】

CompareDbMain是主函数。

【具体代码】

public class ColumnEntity {
    private String tableName;
    private String columnName;
    private String columnTypeName;
    private Integer columnDisplaySize;
    private Integer scale;

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public String getColumnName() {
        return columnName;
    }

    public void setColumnName(String columnName) {
        this.columnName = columnName;
    }

    public String getColumnTypeName() {
        return columnTypeName;
    }

    public void setColumnTypeName(String columnTypeName) {
        this.columnTypeName = columnTypeName;
    }

    public Integer getColumnDisplaySize() {
        return columnDisplaySize;
    }

    public void setColumnDisplaySize(Integer columnDisplaySize) {
        this.columnDisplaySize = columnDisplaySize;
    }

    public Integer getScale() {
        return scale;
    }

    public void setScale(Integer scale) {
        this.scale = scale;
    }
}
public class TableEntity {
    private String tableName; //表名
    private String tableType; //表类型
    private String tableCat; //表所属数据库
    private String tableSchem; //表所属用户名
    private String remarks; //表备注

    public String getTableName() {
        return tableName;
    }

    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    public String getTableType() {
        return tableType;
    }

    public void setTableType(String tableType) {
        this.tableType = tableType;
    }

    public String getTableCat() {
        return tableCat;
    }

    public void setTableCat(String tableCat) {
        this.tableCat = tableCat;
    }

    public String getTableSchem() {
        return tableSchem;
    }

    public void setTableSchem(String tableSchem) {
        this.tableSchem = tableSchem;
    }

    public String getRemarks() {
        return remarks;
    }

    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }
}
import java.sql.*;

/**
 * JDBC工具类
 * 包含数据库连接及关闭数据库资源
 */
public class MysqlDBTools {
    static Connection connection = null;
    static PreparedStatement preparedStatement = null;
    static ResultSet resultSet = null;
    static String DB_URL = "";
    static String DB_USER = "";
    static String DB_PWD = "";

    public MysqlDBTools(String dbUrl, String dbUser, String dbPwd){
        this.DB_URL = dbUrl;
        this.DB_USER = dbUser;
        this.DB_PWD = dbPwd;
    }

    public static Connection getConnection(){
        try{
            Class.forName("com.mysql.cj.jdbc.Driver");
            connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PWD);
        }catch (Exception e){
            System.out.println("连接失败!");
            e.printStackTrace();
        }
        return connection;
    }


    public static void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet){
        if(resultSet != null){
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if(preparedStatement != null){
            try {
                preparedStatement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if(connection != null){
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}
import java.sql.*;
import java.util.*;

/**
 * 功能
 * 更新可能因为数据表结构发生变化导致程序启动失败
 * 此程序能查找对比两个数据库的表结构以及字段的差异
 * 方便查找问题所在
 */
public class CompareDbMain {

    private static String db_url1 = "jdbc:mysql://xx.xx.xx.xx:3306/udesign?useUnicode=true&characterEncoding=utf8&useSSL=false";
    private static String db_user1 = "root";
    private static String db_pwd1 = "xxx";

    private static String db_url2 = "jdbc:mysql://xx.xx.xx.xx:3306/udesign-v2?useUnicode=true&characterEncoding=utf8&useSSL=false";
    private static String db_user2 = "root";
    private static String db_pwd2 = "xxx";

    public static void main(String[] args) throws Exception{
        System.out.println("[结果说明]");
        System.out.println("1. ++表示A比B多,--表示A比B少,**表示有变化");
        System.out.println("");

        Connection conn1 = new MysqlDBTools(db_url1, db_user1, db_pwd1).getConnection();
        Connection conn2 = new MysqlDBTools(db_url2, db_user2, db_pwd2).getConnection();

        //对比表信息
        List<TableEntity> tables1 = getTables(conn1);
        List<TableEntity> tables2 = getTables(conn2);
        StringBuffer tableRes = compareTable(tables1, tables2);
        System.out.println("[表对比结果]");
        System.out.println(conn1.getCatalog() + " vs " + conn2.getCatalog());
        System.out.println(tableRes);

        StringBuffer columnRes = compareColumn(conn1, conn2, tables1, tables2);
        System.out.println("[表字段对比结果]");
        System.out.println(columnRes);
    }


    public static StringBuffer compareColumn(Connection conn1, Connection conn2, List<TableEntity> tables1, List<TableEntity> table2){
        StringBuffer sb = new StringBuffer();
        for(TableEntity t1: tables1){
            if(tableContains(table2, t1)){
                sb.append("["+ t1.getTableName() +"]"  + "\r\n");
                List<ColumnEntity> columnEntities1 = getColumns(conn1, t1);
                List<ColumnEntity> columnEntities2 = getColumns(conn2, t1);

                for(ColumnEntity c1: columnEntities1){
                    if(columnContains(columnEntities2, c1)){
                        ColumnEntity c2 = getColumnFromList(columnEntities2, c1);
                        if(!c2.getColumnDisplaySize().equals(c1.getColumnDisplaySize())
                        || !c2.getColumnTypeName().equals(c1.getColumnTypeName())
                        || !c2.getScale().equals(c1.getScale())){
                            sb.append("  **" + c2.getColumnName() + "\r\n");
                        }
                        //System.out.println("对比字段属性");
                        continue;
                    }
                }

                for(ColumnEntity c2: columnEntities2){
                    if(!columnContains(columnEntities1, c2)){
                        sb.append("  --" + c2.getColumnName() + "\r\n");
                        continue;
                    }
                }

                for(ColumnEntity c1: columnEntities1){
                    if(!columnContains(columnEntities2, c1)){
                        sb.append("  ++" + c1.getColumnName() + "\r\n");
                        continue;
                    }
                }
            }
        }
        return sb;
    }
    //对比表信息
    public static StringBuffer compareTable(List<TableEntity> tab1, List<TableEntity> tab2){
        StringBuffer sb = new StringBuffer();
        for(TableEntity t1: tab1){
            if(tableContains(tab2, t1)){
                sb.append("    " + t1.getTableName() + "\r\n");
                continue;
            }
        }

        for(TableEntity t2: tab2){
            if(!tableContains(tab1, t2)){
                sb.append("  --" + t2.getTableName() + "\r\n");
                continue;
            }
        }

        for(TableEntity t1: tab1){
            if(!tableContains(tab2, t1)){
                sb.append("  ++" + t1.getTableName() + "\r\n");
                continue;
            }
        }

        return sb;
    }
    //获取字段信息
    public static List<ColumnEntity> getColumns(Connection conn, TableEntity table){
        List<ColumnEntity> columnEntities = new LinkedList<>();
        String sql = "select * from " + table.getTableName();
        try {
            PreparedStatement ps = conn.prepareStatement(sql);
            ResultSet rs = ps.executeQuery();
            ResultSetMetaData meta = rs.getMetaData();
            int columnCount = meta.getColumnCount();
            for (int i = 1; i < columnCount + 1; i++) {
                ColumnEntity columnEntity = new ColumnEntity();
                columnEntity.setColumnName(meta.getColumnName(i).toLowerCase());
                columnEntity.setColumnTypeName( meta.getColumnTypeName(i).toLowerCase());
                columnEntity.setColumnDisplaySize(meta.getColumnDisplaySize(i));
                columnEntity.setScale(meta.getScale(i));
                columnEntity.setTableName(meta.getTableName(i).toLowerCase());

                columnEntities.add(columnEntity);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return columnEntities;
    }

    //获取表信息
    public static List<TableEntity> getTables(Connection conn){
        List<TableEntity> tableEntities = new LinkedList<>();
        try {
            DatabaseMetaData dbMetaData = conn.getMetaData();
            ResultSet rs = dbMetaData.getTables(conn.getCatalog(), null, null,new String[] { "TABLE" });
            while (rs.next()) {// ///TABLE_TYPE/REMARKS
                TableEntity table = new TableEntity();
                table.setTableName(rs.getString("TABLE_NAME").toLowerCase());
                table.setTableType(rs.getString("TABLE_TYPE").toLowerCase());
                table.setTableCat(rs.getString("TABLE_CAT").toLowerCase());
                table.setTableSchem(rs.getString("TABLE_SCHEM")==null? "": rs.getString("TABLE_SCHEM").toLowerCase());
                table.setRemarks(rs.getString("REMARKS").toLowerCase());
                tableEntities.add(table);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return tableEntities;
    }

    //从list里面获取
    public static ColumnEntity getColumnFromList(List<ColumnEntity> columnEntities, ColumnEntity column){
        for(ColumnEntity c: columnEntities){
            if(c.getColumnName().equals(column.getColumnName())
                    && c.getTableName().equals(column.getTableName())){
                return c;
            }
        }

        return null;
    }

    public static boolean tableContains(List<TableEntity> tableEntities, TableEntity table){
        for(TableEntity tab: tableEntities){
            if(tab.getTableName().equals(table.getTableName())){
                return true;
            }
        }

        return  false;
    }

    public static boolean columnContains(List<ColumnEntity> columnEntities, ColumnEntity column){
        for(ColumnEntity tab: columnEntities){
            if(tab.getColumnName().equals(column.getColumnName())
                    && tab.getTableName().equals(column.getTableName())){
                return true;
            }
        }

        return false;
    }
}

结果展示:

[结果说明]
1. ++表示A比B多,--表示A比B少,**表示有变化

[表对比结果]
udesign vs udesign-v2
    b_busi_type
    b_busi_type_l2
    c_config_version
    c_datasource_attr
    c_datasource_attr_set
    c_datasource_change_plan
    c_datasource_corba
    c_datasource_ftp
    c_datasource_info
    c_datasource_jdbc
    c_datasource_kafka
    c_datasource_pipe
    c_datasource_sdtp
    c_datasource_snmp
    c_datasource_socket
    c_datasource_subscribe
    c_dict_data_version
    c_dict_devicetype
    c_dict_net_type
    c_dict_protocol
    c_dict_region
    c_dict_specility
    c_dict_specility_level
    c_dict_vendor
    c_image
    c_image_env
    c_kafka_send_log
    c_omc_device_type
    c_omc_info
    c_omc_ne
    c_omc_net_type
    c_redis_monitor
    c_specility_topic
    collect_schedule_file_log
    collect_schedule_ftp_log
    collect_schedule_ftp_log_d
    collect_schedule_ftp_wait
    collect_schedule_time_log
    collect_stage
    collect_stage_log
    collect_stage_rel
    collect_task
    collect_task_log
    group_info
    pars_data_class
    s_protocoltype
    sys_dict
    sys_dict_item
    ue_component
    ue_component_class
    ue_dir
    ue_dir_type
    ue_etl_task_publish
    ue_stage
    ue_stage_meta_rel
    ue_task
    ue_task_publish
    ue_template
    ue_template_stage
    ue_workspace
  ++kafka

[表字段对比结果]
[b_busi_type]
[b_busi_type_l2]
[c_config_version]
[c_datasource_attr]
[c_datasource_attr_set]
[c_datasource_change_plan]
[c_datasource_corba]
[c_datasource_ftp]
[c_datasource_info]
[c_datasource_jdbc]
[c_datasource_kafka]
[c_datasource_pipe]
[c_datasource_sdtp]
[c_datasource_snmp]
[c_datasource_socket]
[c_datasource_subscribe]
[c_dict_data_version]
[c_dict_devicetype]
[c_dict_net_type]
[c_dict_protocol]
[c_dict_region]
  **county_name
[c_dict_specility]
[c_dict_specility_level]
[c_dict_vendor]
[c_image]
[c_image_env]
[c_kafka_send_log]
[c_omc_device_type]
[c_omc_info]
[c_omc_ne]
[c_omc_net_type]
[c_redis_monitor]
[c_specility_topic]
[collect_schedule_file_log]
[collect_schedule_ftp_log]
[collect_schedule_ftp_log_d]
[collect_schedule_ftp_wait]
[collect_schedule_time_log]
[collect_stage]
[collect_stage_log]
[collect_stage_rel]
[collect_task]
  ++group_names
[collect_task_log]
[group_info]
[pars_data_class]
[s_protocoltype]
[sys_dict]
[sys_dict_item]
[ue_component]
[ue_component_class]
[ue_dir]
[ue_dir_type]
[ue_etl_task_publish]
[ue_stage]
[ue_stage_meta_rel]
[ue_task]
[ue_task_publish]
  --group_names
[ue_template]
[ue_template_stage]
[ue_workspace]

1.多了kafka表

2.c_dict_region county_name字段属性不一致

3. collect_task多了group_names字段

4.ue_task_publish少了group_names字段

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

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

相关文章

Spring更简单的存取Bean

在上一篇blog里边我介绍了spring项目的创建以及Bean对象的存储和读取。 存储&#xff1a;1.首先创建Bean对象 2.将Bean对象注册到Spring容器中【Bean标签】 读取&#xff1a;1.获取Spring上下文对象 2.获取指定的Bean对象 3.使用Bean对象 但是随着Bean对象的增多以及使用频率的…

【面试】Java 反射机制(常见面试题)

文章目录 前言一、反射是什么&#xff1f;二、为什么要有反射三、反射 API3.1 获取 Class 对象的三种方式3.2 获取成员变量3.3 获取构造方法3.4.获取非构造方法 四、实践五、常见面试题5.1. 什么是反射&#xff1f;5.2. 哪里用到反射机制&#xff1f;5.3. 什么叫对象序列化&…

IDEA沉浸式编程体验

前言 IntelliJ IDEA:前不久推出了一个新的概念Fleet编辑器。用过的人都知道&#xff0c;不过是模仿VScode整一套&#xff0c;但相比之下&#xff0c;fleet虽然在传统IDEA的基础上简约了不少&#xff0c;一旦打开智能模式&#xff0c;那内存占用刷一下就上去了&#xff0c;没个3…

Apache Atlas(1):Atlas 入门

1 Atlas 概述 Apache Atlas 为组织提供开放式元数据管理和治理功能&#xff0c;用以构建其数据资产目录&#xff0c;对这些资产进行分类和管理&#xff0c;形成数据字典。并为数据分析师和数据治理团队&#xff0c;提供围绕这些数据资产的协作功能。 注&#xff1a;数据字典&…

SpringBoot3 integrate SpringDoc

SpringDoc 官方文档 Springdoc3取代swagger2 pom xml加载Springdoc JarOpenAPIDefinition&#xff0c;声明一个OpenAPI对API进行分组&#xff0c;方便查询访问地址springdoc ConfigurationRequestMapping pom xml加载Springdoc Jar <dependency><groupId>org.sprin…

记录idea插件wl spring assistant plugin的坑-不提示配置项,显示黑树叶

某一天在编写springboot项目的配置文件是&#xff0c;提示我按照插件wl spring assistant。 然后手贱&#xff0c;就安装了。 等第二天在编写配置文件的时候&#xff0c;就遇到了大坑&#xff0c;配置文件无法提示了。 正常情况下&#xff1a; 比如我们输入mybatis-plus的log&a…

mmpose----AnimalKingdom数据集使用mmpose训练

本文主要讲述了使用mmpose训练AnimalKingdom数据集来预测鸟类骨架 1、下载mmpose&#xff0c;AnimalKingdom数据集补充代码 安装 — MMPose 1.0.0 文档根据官方文档安装mmpose可以跑通demo GitHub - sutdcv/Animal-Kingdom: [CVPR2022] Animal Kingdom: A Large and Diverse…

自动化渗透测试自动化挖掘src

文章目录 前言思路资产收集资产收集http服务自动攻击利用 前言 好久没有写blog了&#xff0c;最近在上班干活&#xff0c;最近抽空研究了一下自动化渗透测试&#xff0c;下面分享一下 思路 资产收集 传统的资产收集都是跟域名挂钩&#xff0c;域名收集的好坏也至关重要&…

键盘敲入 A 字母时,操作系统期间发生了什么?

键盘可以说是我们最常使用的输入硬件设备了&#xff0c;但身为程序员的你&#xff0c;你知道「键盘敲入A 字母时&#xff0c;操作系统期间发生了什么吗」&#xff1f; 设备控制器 我们的电脑设备可以接非常多的输入输出设备&#xff0c;比如键盘、鼠标、显示器、网卡、硬盘、打…

ERP与WMS有哪些区别和联系?

一、什么是ERP ERP&#xff08;Enterprise Resource Planning&#xff09;是企业资源计划系统&#xff0c;它是一套综合的管理软件系统&#xff0c;可以帮助企业对各种业务管理、生产制造、供应链、销售财务等进行管理和优化。ERP系统的核心功能包括人力资源管理、物料管理、财…

无线电相关的SCI期刊有哪些? - 易智编译EaseEditing

以下是几个无线电相关的SCI期刊&#xff1a; IEEE Transactions on Wireless Communications&#xff1a; 这是一个IEEE无线通信协会的期刊&#xff0c;主要涵盖了无线通信领域的最新研究进展&#xff0c;包括无线网络&#xff0c;通信系统和信号处理等方面。 IEEE Transacti…

IntelliJ Platform-Plugins-获取鼠标选中字段或方法(PsiElement抽象)

PsiElement接口是文件中光标所在的那个字段&#xff0c;或者光标所在的那个方法的抽象&#xff0c;例如下图中&#xff0c;PsiElement就是private String name 而下图中PsiElement就是public String getName() 下面的代码会演示&#xff1a;光标在方法上&#xff0c;就打印方…

HTMLCSS

1、HTML 1.1 介绍 HTML 是一门语言&#xff0c;所有的网页都是用HTML 这门语言编写出来的&#xff0c;也就是HTML是用来写网页的&#xff0c;像京东&#xff0c;12306等网站有很多网页。 这些都是网页展示出来的效果。而HTML也有专业的解释 HTML(HyperText Markup Language)…

【EKF】卡尔曼滤波原理

前言 本篇是最近在学习云台以及姿态融合时&#xff0c;想学习一下卡尔曼滤波的原理&#xff0c;基于 DR_CAN 老师的卡尔曼滤波的视频做的笔记&#xff0c;基本上是按照 DR_CAN 老师的思路自己推导计算了一遍&#xff0c;推荐还是看一下原视频&#xff0c;讲解得很不错&#xf…

5款写作神器,帮助你写出5w+爆款文案,好用到哭

我不允许还有文案小白、新手博主不知道这5款写作利器&#xff01; 每次一写文案就头秃的新媒体工作者&#xff0c;赶紧看过来吧&#xff01;这5款好用到爆的写作神器&#xff0c;喝一杯咖啡的时间就能完成写作。 我和同事都是用它们&#xff0c;出了很多的爆款&#xff0c;现…

shell脚本--函数

目录 一&#xff1a;shell函数定义 1.函数的含义 2.函数的优点 3.函数的格式 4.函数返回值 &#xff08;1&#xff09;return输出 &#xff08;2&#xff09;echo输出 二&#xff1a;函数传参 1.情景一 2.情景二 3.情景三 4.情景四 三:递归函数 1.递归函数定义 2.通过…

STM32F103ZET6驱动TOF250激光测距传感器

STM32驱动TOF250激光测距传感器 TOF250介绍I2C通讯协议I2C寄存器地址 TOF250引脚说明和STM32的接线和STM32的接线 程序实验结果总结 TOF250介绍 TOF250是一款基于TOF原理的单点测距雷达&#xff0c;采用940nm红外光源&#xff0c;提供了精确和可重复的远 距离测量用于高速自动对…

OceanBase写入限速源码解读

一、简介 OceanBase中的写入限速机制旨在控制系统中写入操作&#xff08;一般写入操作包括插入、更新和删除等&#xff09;的速率&#xff0c;目的是为了提高数据库系统的稳定性。本文主要通过以下2个参数来解释写入限速的实现机制。 **1.**writing_throttling_trigger_perce…

MySQL-----索引特性

文章目录 前言一、没有索引,可能会有什么问题二、认识磁盘MySQL与存储先来研究一下磁盘在看看磁盘中一个盘片扇区结论磁盘随机访问(Random Access)和连续访问(Sequential Access) 三、MySQL与磁盘交互的基本单位四、建立共识五、索引的理解建立测试表插入多条记录查看插入结果中…

程序员最终会被自己开发的轮子所淘汰吗?

螺丝刀和扳手的发明&#xff0c;并没有让工人下岗&#xff1b; 工程机械&#xff08;挖掘机等&#xff09;的发明&#xff0c;也不会让建筑工人的需求量减少&#xff1b; 现代医学的各种先进设备&#xff0c;似乎也没有让医生数量大幅减少&#xff1b; …… 所以&#xff0c;关…