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

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

时间:2024-10-23 11:21:40浏览次数:3  
标签:数据恢复 EXE String frame add static new JLabel 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.恢复成功

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

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

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

标签:数据恢复,EXE,String,frame,add,static,new,JLabel,idb
From: https://blog.csdn.net/xh365647/article/details/143178958

相关文章

  • 如何恢复 Windows 上 PostgreSQL 14 中被误删的 pg_restore.exe
    如何恢复Windows上PostgreSQL14中被误删的pg_restore.exe方法1:重新安装PostgreSQL14下载PostgreSQL14安装包:前往PostgreSQL官方网站。下载与操作系统版本匹配的PostgreSQL14安装包。安装PostgreSQL:运行安装程序,进行标准安装。安装过程中,选择“Cli......
  • 麒麟系统通过CrossOver软件安装Windows软件(.exe)的详细过程
    1、安装CrossOver要先更新一下软件集:sudoaptupdate再安装KWRE版的微信。sudoaptinstallkylin-kwre-wechat安装成功后打开CrossOver程序:2、添加windows容器介绍:容器有Windows98、windows2000、windowsXP、windowsVista、windows7、windows8、windows1......
  • 生产数据恢复系列之使用闪回查询恢复Oracle delete误删数据
    一、背景在日常运维过程中,如果不小心使用高危命令删除了数据库的数据,如果没有数据备份,记住不要跑路噢,跟着我一起学习如何恢复数据。二、概念普及UNDO表的作用Undo表存储了已提交和未提交事务所产生的旧数据版本,在需要回滚事务或实现并发控制时使用。每当对数据库进行DM......
  • go1.18版本下 beego/bee安装无法生成exe问题已解决
    转自: https://www.cnblogs.com/leijiangsheng/p/17392795.html我原来的项目是教育学习APP使用gin框架,很多东西都是自己原来实现的。最近开发小程序,需要重新独立后台,又重新找了下go框架研究了下,beego确实是个好框架,至少项目能用到的都考虑进去了。然后发现我本地装了一个下午,be......
  • 闪迪SanDisk固态硬盘维修数据恢复
    固态硬盘(SSD)维修和数据恢复是一个复杂的过程,涉及多个步骤和工具。以下是一些关键的步骤和建议,以帮助您有效地进行固态硬盘的维修和数据恢复:一、固态硬盘维修检查连接:打开计算机主机箱,检查固态硬盘的SATA或NVMe接口连接线是否插紧,是否有松动或断裂。重新插拔连接线,然后重启计算......
  • RAID5数据恢复—raid5阵列如何重组?raid5阵列重组方法详解
    RAID5数据恢复环境:一台存储上有一组由12块SCSI硬盘(11块数据盘+1块热备盘)组建的RAID5磁盘阵列,FreeBSD操作系统+zfs文件系统。RAID5故障:其中一块盘出现故障,需要重组该raid5磁盘阵列。RAID5数据恢复过程:1、将存储关机,将存储中所有磁盘标记后从槽位上取出。以只读方式将所有磁盘进......
  • TF卡长期不用会丢失数据吗?TF卡数据恢复容易吗?
    在现代科技快速发展的时代,TF卡(TransFlash卡)作为便携式存储设备,广泛应用于手机、相机、无人机等多种电子设备中,成为我们日常存储照片、视频、文档等重要数据的得力助手。然而,关于TF卡长期不使用是否会丢失数据,以及TF卡数据恢复难易程度的问题,一直是用户关注的焦点。本文将从这两......
  • 桌面软件/exe程序软件自动化大宝剑--lackey之二次封装以及selenium模仿
    1#lackey二次封装23classlackeyAtion(object):45#初始化,有需要再加6def__init__(self):7self.lackey=lackey.Screen(0)8self.lackey.setAutoWaitTimeout(30)910#截屏需要保存路径,截图的名字11de......
  • QT项目打包成exe文件-非常详细(侧重于解决输出的exe文件没有原项目功能的问题)
    写在前面: 我是研二学生,用qt给老师项目做的一个辅助软件。项目要验收,所以需要打包qt项目成exe文件,但是我死活弄不出来,来回搞了两三天才弄好。特此写下第一篇博客,记录这个过程,并给同样困扰的新手朋友们提供一个方法。我是一个新手,期待大家的批评指正。打包流程: 1、获取初始......
  • 【编程入门】BMI.exe
    #include<bits/stdc++.h>usingnamespacestd;intmain(){   doubleh,w,b;   cin>>h>>w;   h/=100;   b=w/(h*h);   if(b>24)   {      cout<<"Toofat!"<<endl;      doublew24=......