当前位置: 首页 > news >正文

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

文章目录

  • 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; // 显示文件夹路径的标签1private static JLabel folderPathLabel2; // 显示文件夹路径的标签2public 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 {@Overridepublic 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.恢复成功

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

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

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

相关文章:

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

文章目录 1.代码2.Main方法打包3.Jar包打成exe可执行文件4.使用(1.)准备一个表结构一样得数据库(2.)打开软件(3.)输入路径 5.恢复成功 本文档只是为了留档方便以后工作运维,或者给同事分享文档内…...

Spring Boot面试题

1.什么是SpringBoot?它的主要特点是什么? Spring Boot 是一个基于 Spring 框架的开发和构建应用程序的工具,它旨在简化 Spring 应用的初始搭建和开发过程。Spring Boot 提供了一种约定优于配置的方式,通过自动配置和默认值&#…...

原生页面引入Webpack打包JS

Webpack简介 概述: Webpack是一个现代JavaScript应用程序的静态模块打包器。它将应用程序中的每个文件视为一个模块,并通过配置规则来解析这些模块之间的依赖关系,最终将其打包成一个或多个浏览器可以执行的文件。动态加载(Code …...

健康之路押注医药零售:毛利率下滑亏损扩大,医疗咨询人次大幅减少

《港湾商业观察》黄懿 2024年9月13日,健康之路股份有限公司(下称“健康之路”)再次递表港交所,建银国际为独家保荐人。健康之路国内运营主体为健康之路(中国)信息技术有限公司和福建健康之路信息技术有限公…...

【人工智能-初级】第7章 聚类算法K-Means:理论讲解与代码示例

文章目录 一、K-Means聚类简介二、K-Means 聚类的工作原理2.1 初始化簇中心2.2 分配簇标签2.3 更新簇中心2.4 迭代重复2.5 K-Means 算法的目标三、K-Means 聚类的优缺点3.1 优点3.2 缺点四、K 值的选择五、Python 实现 K-Means 聚类5.1 导入必要的库5.2 生成数据集并进行可视化…...

HOT 100 技巧题(136/169/75/31/287)

136. 只出现一次的数字 技巧类型题目,通过异或运算实现 169. 多数元素 三种常见解法:1. 哈希2. 排序3. 投票法 75. 颜色分类 单指针 两次遍历:第一次遍历把所有0都交换到前面,记录最后一个0的位置index,第二次遍…...

什么是时间戳?怎么获取?有什么用?

在 JavaScript 中,时间戳通常表示为自 1970 年 1 月 1 日 00:00:00 UTC 以来的毫秒数。我们可以使用 Date 对象来获取当前时间的时间戳,或者将特定的日期转换为时间戳。在JavaScript中,时间戳通常以毫秒为单位表示。 如何获取时间戳 在Java…...

LeetCode:459重复的子字符串

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。 示例 1: 输入: s "abab" 输出: true 解释: 可由子串 "ab" 重复两次构成。示例 2: 输入: s "aba" 输出: false示例 3: 输入: s "abcabcabcabc" 输…...

【含开题报告+文档+PPT+源码】基于SSM的旅游与自然保护平台开发与实现

开题报告 围场县拥有丰富的自然景观和野生动植物资源,同时面临着旅游业发展和自然保护之间的平衡问题,通过强调自然保护,这个平台可以教育游客如何尊重和保护当地的生态环境。同时,平台还可以提供关于生态保护的信息,…...

【ANTs】医疗影像工具ANTs多种安装方式教程

介绍ANTs的几种简单的安装教程 基于Releases的安装 Github上选择适配自己操作系统的安装包,链接: link 一般使用最新版本。这里官方操作说明,支持Ubuntu、MacOS、CentOS,但是windows有安装包,不知道怎么用。。。 下载后有两个文件夹,bin和lib,bin里面长这样(图示wind…...

想要音频里的人声,怎么把音频里的人声和音乐分开?

在音频处理领域,将音频中的人声和音乐分开是一个常见需求,尤其对于音乐制作、影视后期以及个人娱乐应用来说,这种分离技术显得尤为重要。随着科技的发展,现在已经有多种方法可以实现这一目的。 一、使用专业音频处理软件 市面上有…...

python代码中通过pymobiledevice3访问iOS沙盒目录获取app日志

【背景】 在进行业务操作过程中,即在app上的一些操作,在日志中会有对应的节点,例如,下面是查看设备实时视频过程对应的一些关键节点: 1、TxDeviceAwakeLogicHelper:wakeStart deviceId CxD2BA11000xxxx …...

Spring AOP 使用方法总结

AOP切面编程的最佳应用场景 记录日志性能监控事务管理处理异常数据验证,验证传入参数的正确性(一般不用这个方法做,而是用拦截器) spring提供了以下注解供开发者使用,编写AOP程序 Aspect 申明切面Pointcut 切点&#…...

LeetCode 每日一题 2024/10/21-2024/10/27

记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步 目录 10/21 910. 最小差值 II10/22 3184. 构成整天的下标对数目 I10/23 3185. 构成整天的下标对数目 II10/24 3175. 找到连续赢 K 场比赛的第一位玩家10/25 3180. 执行操作可获得…...

不到1500元的I卡可以玩转3A大作吗?撼与科技Intel Arc A750显卡游戏性能实

一、前言 还记得2022年10月的时候,英特尔发布了Arc A750和A770显卡,和此前所发布的DG1、A380不同,这两张显卡可以说是真正意义上的游戏显卡。不知不觉间,两年已经过去了,在这两年期间,英特尔不仅在积极地打…...

STK与MATLAB互联——仿真导航卫星与地面用户间距离和仰角参数

文章目录 构建GPS星座创建单个PRN的GPS卫星创建GPS星座,并为其添加发射机 北斗星座构建搭建低轨铱星星座构建一颗轨道高度为800km/1000km/1200km的低轨卫星构建一颗轨道高度为800km/1000km/1200km的低轨卫星建立地面站,可见性分析确定地面站坐标分析单颗…...

js面试问题笔记(一)

一.热门js面试 1.简述同步和异步的区别? 同步: 浏览器访问服务器请求,用户看到页面刷新 ,重新发请求,等请求完,页面刷新,新内容出现,用户看到新内容,进行下一步操作 异步: 浏览器访问服务器请求,用户正常操作,浏览器后端进行请求,等请求完,页面不刷新,新内容也会出现,用户看到…...

pip 和 pipx 的主要区别?

特性pippipx用途用于安装Python库或命令行应用程序,可以安装带entry points的库专门用于安装和管理Python命令行工具,每个工具都在隔离的虚拟环境中运行虚拟环境不自动创建虚拟环境,需要手动使用 venv 或 virtualenv 创建自动为每个安装的工具…...

4457M数字示波器

_XLT新利通_ 4457M数字示波器 带宽500MHz到3GHz 4457M系列数字示波器产品,包含4457DM/EM/FM/GM四个产品型号,模拟通道数4、8个,带宽500MHz到3GHz,最高采样率10GSa/s,垂直分辨率8bit,最大存储深度2Gpts。…...

【永中软件-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

什么是EULA和DPA

文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

管理学院权限管理系统开发总结

文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)

前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块&#xff0c…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...

Python 训练营打卡 Day 47

注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...

深度解析:etcd 在 Milvus 向量数据库中的关键作用

目录 🚀 深度解析:etcd 在 Milvus 向量数据库中的关键作用 💡 什么是 etcd? 🧠 Milvus 架构简介 📦 etcd 在 Milvus 中的核心作用 🔧 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...