MySQL根据.idb数据恢复脚本,做成了EXE可执行文件

news2024/10/23 17:29:40

文章目录

  • 1.代码
  • 2.Main方法打包
  • 3.Jar包打成exe可执行文件
  • 4.使用
    • (1.)准备一个表结构一样得数据库
    • (2.)打开软件
    • (3.)输入路径
  • 5.恢复成功

本文档只是为了留档方便以后工作运维,或者给同事分享文档内容比较简陋命令也不是特别全,不适合小白观看,如有不懂可以私信,上班期间都是在得

前文连接=====》mysql8 使用idb文件实现数据备份

需求,昨天写个数据恢复呗同事嫌麻烦,让我写个脚本一键恢复,一开始想着存储过程,但是存储过程不能移动文件,索性写个可视化界面吧。
下面直接cv就行了

1.代码

package com.joxp.mysql;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class MySQLConnectionApp {
    private static JFrame frame; // 主窗口
    private static JTextField userField; // 用户名输入框
    private static JPasswordField passwordField; // 密码输入框
    private static JTextField dbNameField; // 数据库名称输入框
    private static String selectedFolder1; // 第一个选择的文件夹路径
    private static String selectedFolder2; // 第二个选择的文件夹路径
    private static JLabel folderPathLabel1; // 显示文件夹路径的标签1
    private static JLabel folderPathLabel2; // 显示文件夹路径的标签2

    public static void main(String[] args) {
        SwingUtilities.invokeLater(MySQLConnectionApp::createAndShowGUI);
    }

    private static void createAndShowGUI() {
        frame = new JFrame("MySQL 连接器");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);
        frame.setLayout(new GridLayout(5, 2));

        JLabel userLabel = new JLabel("用户名:");
        userField = new JTextField();
        JLabel passwordLabel = new JLabel("密码:");
        passwordField = new JPasswordField();
        JLabel dbNameLabel = new JLabel("数据库名:");
        dbNameField = new JTextField();
        // 创建右下角的标签
        JLabel footerLabel = new JLabel("By:XHao");
        footerLabel.setHorizontalAlignment(SwingConstants.LEFT); // 左对齐
        JButton connectButton = new JButton("连接");
        connectButton.addActionListener(new ConnectAction());
        JLabel messageLabel = new JLabel("", SwingConstants.CENTER);
        frame.add(userLabel);
        frame.add(userField);
        frame.add(passwordLabel);
        frame.add(passwordField);
        frame.add(dbNameLabel);
        frame.add(dbNameField);
        frame.add(connectButton);
        frame.add(messageLabel);
        frame.add(footerLabel); // 添加 footerLabel 到最后
        frame.setVisible(true);
    }

    private static void updateUIAfterConnection() {
        frame.getContentPane().removeAll();
        frame.setLayout(new GridLayout(5, 1)); // 新布局为5行1列
        frame.setSize(700, 350); // 根据需要调整宽度和高度
        JButton selectFolderButton1 = new JButton("选择备份文件夹");
        JButton selectFolderButton2 = new JButton("选择恢复文件夹");
        JButton queryButton = new JButton("查询数据路径");
        JButton recoverButton = new JButton("恢复数据");
        JLabel queryResultLabel = new JLabel(""); // 用于显示查询结果
        // 固定按钮大小
        Dimension buttonSize = new Dimension(80, 30);
        selectFolderButton1.setPreferredSize(buttonSize);
        selectFolderButton2.setPreferredSize(buttonSize);
        queryButton.setPreferredSize(buttonSize);
        recoverButton.setPreferredSize(buttonSize);

        folderPathLabel1 = new JLabel("未选择文件夹");
        folderPathLabel1.setSize(80, 30);
        folderPathLabel2 = new JLabel("未选择文件夹");
        folderPathLabel2.setSize(80, 30);
        selectFolderButton1.addActionListener(e -> {
            selectedFolder1 = openFolderChooser();
            folderPathLabel1.setText(selectedFolder1 != null ? selectedFolder1 : "未选择文件夹");
        });
        // 创建右下角的标签
        JLabel footerLabel = new JLabel("By:XHao");
        JLabel aaa = new JLabel("");
        footerLabel.setHorizontalAlignment(SwingConstants.LEFT); // 左对齐
        aaa.setHorizontalAlignment(SwingConstants.LEFT); // 左对齐
        selectFolderButton2.addActionListener(e -> {
            selectedFolder2 = openFolderChooser();
            folderPathLabel2.setText(selectedFolder2 != null ? selectedFolder2 : "未选择文件夹");
        });
        queryButton.addActionListener(e -> {
            String result = executeQuery(); // 假设 executeQuery() 返回查询结果
            queryResultLabel.setText(result); // 显示在下方标签
        });
        recoverButton.addActionListener(e -> executeRecovery());
        // 将按钮和标签添加到框架中
        frame.add(selectFolderButton1);
        frame.add(folderPathLabel1);
        frame.add(selectFolderButton2);
        frame.add(folderPathLabel2);
        frame.add(queryButton);
        frame.add(recoverButton);
        frame.add(queryResultLabel);
        frame.add(aaa, BorderLayout.SOUTH);
        frame.add(footerLabel, BorderLayout.SOUTH); // 将footerLabel放在底部
        frame.revalidate();
        frame.repaint();
    }

    private static String openFolderChooser() {
        JFileChooser folderChooser = new JFileChooser();
        folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int returnValue = folderChooser.showOpenDialog(frame);
        if (returnValue == JFileChooser.APPROVE_OPTION) {
            File selectedFolder = folderChooser.getSelectedFile();
            return selectedFolder.getAbsolutePath();
        }
        return null;
    }

    private static String executeQuery() {
        String query = "SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(@@datadir, '/', -1), '/', 1) as aa;";
        try (Connection conn = getConnection();
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(query)) {
            StringBuilder result = new StringBuilder();
            while (rs.next()) {
                result.append(rs.getString("aa")).append("\n");
            }
            if (result.length() == 0) {
                result.append("没有找到任何结果。");
            }
            return result.toString();
        } catch (SQLException e) {
            showErrorDialog("查询失败: " + e.getMessage());
        }
        return null;
    }

    private static void executeRecovery() {
        // 第一步,执行第一个存储过程
        try (Connection conn = getConnection();
             Statement stmt = conn.createStatement()) {
            String dropProcedureSQL = "DROP PROCEDURE IF EXISTS " + "your_first_stored_procedure" + ";";
            stmt.execute(dropProcedureSQL);
            // 创建存储过程
            String abc = "CREATE DEFINER=`root`@`%` PROCEDURE `your_first_stored_procedure`(IN dbName VARCHAR(255))\n" +
                    "BEGIN\n" +
                    "    DECLARE done INT DEFAULT FALSE;\n" +
                    "    DECLARE tableName VARCHAR(255);\n" +
                    "\n" +
                    "    -- 定义游标\n" +
                    "    DECLARE cur CURSOR FOR \n" +
                    "        SELECT TABLE_NAME \n" +
                    "        FROM information_schema.TABLES \n" +
                    "        WHERE TABLE_SCHEMA = dbName;\n" +
                    "\n" +
                    "    -- 错误处理\n" +
                    "    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION\n" +
                    "        BEGIN\n" +
                    "            -- 错误发生时不做任何处理,继续执行\n" +
                    "        END;\n" +
                    "\n" +
                    "    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;\n" +
                    "\n" +
                    "    -- 第一个循环:遍历所有表并执行 DISCARD TABLESPACE\n" +
                    "    OPEN cur;\n" +
                    "\n" +
                    "    read_loop_1: LOOP\n" +
                    "        FETCH cur INTO tableName;\n" +
                    "        IF done THEN\n" +
                    "            LEAVE read_loop_1;\n" +
                    "        END IF;\n" +
                    "\n" +
                    "        -- 执行 DISCARD TABLESPACE\n" +
                    "        SET @discard_sql = CONCAT('ALTER TABLE ', dbName, '.', tableName, ' DISCARD TABLESPACE;');\n" +
                    "        PREPARE stmt FROM @discard_sql;\n" +
                    "        EXECUTE stmt;\n" +
                    "        DEALLOCATE PREPARE stmt;\n" +
                    "\n" +
                    "        -- 在此处可以执行其他操作\n" +
                    "        -- 例如:INSERT INTO logging_table (message) VALUES (CONCAT('Discarded tablespace for ', tableName));\n" +
                    "    END LOOP;\n" +
                    "\n" +
                    "    -- 关闭游标\n" +
                    "    CLOSE cur;\n" +
                    "END;";

        // 执行创建存储过程
            stmt.execute(abc);
            stmt.execute("CALL your_first_stored_procedure('" + dbNameField.getText() + "')");
            stmt.execute(dropProcedureSQL);
            // 第二步,复制文件
            if (selectedFolder1 != null && selectedFolder2 != null) {
                copyFiles(selectedFolder1, selectedFolder2);
            } else {
                showErrorDialog("请确保选择了两个文件夹。");
                return;
            }
            String aaaa = "DROP PROCEDURE IF EXISTS " + "your_second_stored_procedure" + ";";
            stmt.execute(aaaa);
            // 创建存储过程
            String aa = " CREATE DEFINER=`root`@`%` PROCEDURE `your_second_stored_procedure`(IN dbName VARCHAR(255))\n" +
                    "BEGIN\n" +
                    "    DECLARE done INT DEFAULT FALSE;\n" +
                    "    DECLARE tableName VARCHAR(255);\n" +
                    "\n" +
                    "    -- 定义游标\n" +
                    "    DECLARE cur CURSOR FOR \n" +
                    "        SELECT TABLE_NAME \n" +
                    "        FROM information_schema.TABLES \n" +
                    "        WHERE TABLE_SCHEMA = dbName;\n" +
                    "\n" +
                    "    -- 错误处理\n" +
                    "    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION\n" +
                    "        BEGIN\n" +
                    "            -- 错误发生时不做任何处理,继续执行\n" +
                    "        END;\n" +
                    "\n" +
                    "    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;\n" +
                    "\n" +
                    "    -- 重新打开游标\n" +
                    "    OPEN cur;\n" +
                    "\n" +
                    "    read_loop_2: LOOP\n" +
                    "        FETCH cur INTO tableName;\n" +
                    "        IF done THEN\n" +
                    "            LEAVE read_loop_2;\n" +
                    "        END IF;\n" +
                    "\n" +
                    "        -- 执行 IMPORT TABLESPACE\n" +
                    "        SET @import_sql = CONCAT('ALTER TABLE ', dbName, '.', tableName, ' IMPORT TABLESPACE;');\n" +
                    "        PREPARE stmt FROM @import_sql;\n" +
                    "        EXECUTE stmt;\n" +
                    "        DEALLOCATE PREPARE stmt;\n" +
                    "\n" +
                    "        -- 在此处可以执行其他操作\n" +
                    "        -- 例如:INSERT INTO logging_table (message) VALUES (CONCAT('Imported tablespace for ', tableName));\n" +
                    "    END LOOP;\n" +
                    "\n" +
                    "    -- 关闭游标\n" +
                    "    CLOSE cur;\n" +
                    "END;\n";
            stmt.execute(aa);
            // 第三步,执行第二个存储过程
            stmt.execute("CALL your_second_stored_procedure('" + dbNameField.getText() + "')"); // 替换为你的存储过程名
            stmt.execute(aaaa);
            JOptionPane.showMessageDialog(frame, "恢复数据成功。", "成功", JOptionPane.INFORMATION_MESSAGE);
        } catch (SQLException e) {
            showErrorDialog("执行存储过程失败: " + e.getMessage());
        } catch (IOException e) {
            showErrorDialog("文件复制失败: " + e.getMessage());
        }
    }

    private static void copyFiles(String sourceFolder, String destFolder) throws IOException {
        Path sourcePath = Paths.get(sourceFolder);
        Path destPath = Paths.get(destFolder);
        Files.walk(sourcePath).forEach(source -> {
            Path dest = destPath.resolve(sourcePath.relativize(source));
            try {
                if (Files.isDirectory(source)) {
                    Files.createDirectories(dest);
                } else {
                    Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    private static Connection getConnection() throws SQLException {
        String username = userField.getText();
        String password = new String(passwordField.getPassword());
        String dbName = dbNameField.getText();
        String url = "jdbc:mysql://localhost:3306/" + dbName;
        return DriverManager.getConnection(url, username, password);
    }

    private static class ConnectAction implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            try {
                Class.forName("com.mysql.cj.jdbc.Driver");
                getConnection();
                updateUIAfterConnection();
            } catch (ClassNotFoundException ex) {
                showErrorDialog("驱动未找到: " + ex.getMessage());
            } catch (SQLException ex) {
                showErrorDialog("连接失败: " + ex.getMessage());
            }
        }
    }

    private static void showErrorDialog(String message) {
        JOptionPane.showMessageDialog(frame, message, "连接错误", JOptionPane.ERROR_MESSAGE);
    }
}

2.Main方法打包

Main方法打包教程

3.Jar包打成exe可执行文件

使用launch4j把Jar包打成exe教程

4.使用

(1.)准备一个表结构一样得数据库

数据库

(2.)打开软件

软件

打开软件输入账号密码和要恢复得库

(3.)输入路径

在这里插入图片描述
在这里插入图片描述

点击恢复

5.恢复成功

在这里插入图片描述
在这里插入图片描述

待优化,理论上只需要输入备份得文件夹,但是领导催我干别的了,以后有机会在优化一下。

如果点赞多,评论多会更新详细教程,待补充。

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

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

相关文章

查看Chrome安装路

谷歌Google浏览器查看安装路径,浏览器Google Chrome浏览器查看安装路径 chrome://version/ 来源:笔记云

(数据结构)单链表——C语言

目录 1 概念与结构 1.1 结点 1.2 链表的性质 2 实现单链表 2.1打印SLPrint 2.2申请一个结点SLBuyNode 2.3尾插SLPushBack 2.4头插SLPushfront 2.5尾删SLPopBack 2.6头删SLPopfront 2.7查找结点位置SLFindNode 2.8在pos位置插入SLInsert 2.9在pos节点之后插入SLInse…

2024HarmonyOS应用开发者高级认证 最新题库第二部分

单选题 1.以下哪个装饰器用来表示并发共享对象。(D) AShared BState CStyle DSendable 2.hiAppEvent提供的Watcher接口,需要订阅到OS的崩溃事件,正确的实现方式(选下面这个) hiAppEvent.addWatcher({ name:"watcher&…

探索网页组件化:原生JavaScript动态加载HTML与iframe的使用与比较

在网页设计中,将内容作为组件动态加载到页面上是一种提高用户体验和页面性能的有效手段。本文将详细介绍两种实现动态内容加载的方法:使用原生JavaScript动态加载HTML和使用iframe,并对比它们的使用方式和优缺点。 原生JavaScript动态加载HTM…

[论文笔记]HERMES 3 TECHNICAL REPORT

引言 今天带来论文HERMES 3 TECHNICAL REPORT,这篇论文提出了一个强大的工具调用模型,包含了训练方案介绍。同时提出了一个函数调用标准。 为了简单,下文中以翻译的口吻记录,比如替换"作者"为"我们"。 聊天模…

RISC-V笔记——内存模型总结

1 前言 Memory consistency model定义了使用Shared memory(共享内存)执行多线程(Multithread)程序所允许的行为规范。RISC-V使用的内存模型是RVWMO(RISC-V Weak Memory Ordering),RVWMO内存模型是根据全局内存顺序(global memory order)定义的,全局内存…

简单有效修复d3d9.dll错误,11种d3d9.dll错误详细解决办法教程

当你遇到d3d9.dll文件丢失的问题时,可以通过今天的这篇文章详细的步骤来尝试修复这个问题,今天将教大家十一种d3d9.dll丢失修复的方法。 1. 重新安装DirectX以恢复d3d9.dll d3d9.dll是DirectX的一部分,因此重新安装DirectX通常可以解决d3d9.…

proguard对java代码进行混淆加密。并进行反编译测试,后续可配合classfinal进行使用

文章目录 1.插件混淆(1.)pom配置(2.)混淆配置(3.)打包 2.反编译查看效果(1.)工具下载(2.)反编译对比 3.启动测试4.功能测试5.二次加密 本文档只是为了留档方便…

【ChatGPT插件漏洞三连发之一】未授权恶意插件安装

漏洞 要了解第一个漏洞,我们必须首先向您展示 OAuth 身份验证的工作原理: 假设您是 Dan,并且您想使用您的 Facebook 帐户连接到 Example.com。当您点击“使用Facebook登录”时会发生什么? 在步骤 2-3 中: 在 Dan 单…

2024成为自动化测试的7种技能!

随着敏捷和DevOps等新时代项目开发方法逐渐取代旧的瀑布模型,测试需求在业界不断增长。测试人员现在正在与开发人员一起工作,自动化测试在许多方面极大地取代了手动测试。如果您是自动化测试领域的新手,刚雇用您的组织将期望您快速&#xff0…

java线程的几种状态

线程的所有状态 NEW: 安排了工作, 还未开始行动RUNNABLE: 可工作的. 又可以分成正在工作中和即将开始工作. BLOCKED: 这几个都表示排队等着其他事情 WAITING: 这几个都表示排队等着其他事情TIMED_WAITING: 这几个都表示排队等着其他事情TERMINATED: 工作完成了. 线程状态和状…

《黑神话悟空》各章节boss顺序汇总

第一章BOSS顺序: 1、牯护院:犀牛精,位于苍狼岭娟,击败后能获得定身术。 2、广智:火刀狼, 位于观音禅院,击败后获得广智变身,记得敲钟。 3、蓝皮幽魂:蓝皮大头&#xff0…

大模型入门到精通!大模型应用开发极简入门(含PDF)

大模型的出现正悄然改变人们的生活与工作方式,比如ChatGPT-4、文心一言、通义千问等语言大模型。它们已帮助很多办公室“白领”们在解决日常工作问题,如制定计划、撰写实施方案,甚至制作美化PPT等(笔者及身边的同事在工作中还经常…

Star Tower:智能合约的安全基石与未来引领者

在区块链技术的快速发展中,智能合约作为新兴的应用形式,正逐渐成为区块链领域的重要组成部分。然而,智能合约的可靠性问题一直是用户最为关心的焦点之一。为此,Star Tower以其强大的技术实力和全面的安全保障措施,为智…

pytest中@pytest.fixture常用顺序function

ytest中pytest.fixture用法讲解 1、测试函数开始之前2、执行测试函数:3、测试函数结束后: 备注:内容来自chatGPT 在 pytest 中,pytest.fixture 是一个非常强大的功能,用于设置测试所需的环境和状态。它可以通过 scope…

听泉鉴宝在三个月前已布局商标注册!

近日“听泉鉴宝”以幽默的风格和节目效果迅速涨粉至2500多万,连线出现“馆藏文物”和“盗墓现场”等内容,听泉鉴宝早在几个月前已布局商标注册。 据普推知产商标老杨在商标局网站检索发现,“听泉鉴宝”的主人丁某所持股的江苏灵匠申请了三十…

R语言统计分析——置换检验2

参考资料&#xff1a;R语言实战【第2版】 独立两样本和K样本检验 # 安装coin包 install.packages(c("coin")) # 加载coin包 library(coin) # 创建检验数据集 score<-c(40,57,45,55,58,57,64,55,62,65) treatment<-factor(c(rep("A",5),rep("B…

51单片机应用——直流电机PWM调速

目标实现功能 单片机引脚输出PWM波形控制直流电机以不同转速工作。 1.PWM简介 PWM技术 PWM的中文全称是脉宽调制&#xff0c;常用于电动机控制、开关电源、音频放大器等。利用PWM技术可以达到微处理器&#xff08;如单片机&#xff09;的数字输出对模拟电路控制的效果。 P…

膜结构首次应用于国内游轮项目—轻空间

轻空间&#xff08;江苏&#xff09;膜科技有限公司近日成功中标一项国内游轮项目&#xff0c;这一成就标志着膜结构在游轮船舶行业的首次应用&#xff0c;开启了新的市场探索之旅。 作为行业先锋&#xff0c;轻空间始终致力于将创新技术融入多元化场景。本次游轮项目的成功中标…

Opensearch集群部署【docker、服务器、Helm多种部署方式】

操作系统兼容性 我们建议在 Red Hat Enterprise Linux (RHEL) 或使用systemd的基于 Debian 的 Linux 发行版上安装 OpenSearch &#xff0c;例如 CentOS、Amazon Linux 2 和 Ubuntu Long-Term Support (LTS)。OpenSearch 应该适用于大多数 Linux 发行版&#xff0c;但我们只测…