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。…...
【永中软件-注册/登录安全分析报告】
前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 暴力破解密码,造成用户信息泄露短信盗刷的安全问题,影响业务及导致用户投诉带来经济损失,尤其是后付费客户,风险巨大,造成亏损无底洞…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...
用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法
用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...
【版本控制】GitHub Desktop 入门教程与开源协作全流程解析
目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork(创建个人副本)步骤 2: Clone(克隆…...
