java 实现对数据表的备份与还原(备份与还原 到服务器中)

news2024/10/6 2:23:46

java备份还原表数据

背景

需求:这个功能还是费了我一段时间才完成,大体的需求是这样的。 首先是
分模块,每个模块有不同的几个表,备份的时候就按照模块来备份数据,相当于一次性备份多张表的数据了,模块 和 模块拥有的表都是能配置的(即增删改查),主要是选择模块来备份这个麻烦点

思路

  • 备份
    备份的话我想到的是可以用导出xml文件的形式,第二种的话只用用mysql原生的mysqldump命令就好。
    最后用的mysqldump命令,这个容易实现一些。
  • 还原
    还原我查了下有 source 命令还原的,还有使用 mysqldump -h 主机IP -uroot -p db < /root/db.sql 命令进行还原的
    我使用的是后面一种。

命令使用方法

mysqldump命令

1.备份数据库

  • 备份所有数据库
mysqldump -h 主机IP -uroot -p --all-database > /usr/dball.sql
  • 备份多个数据库
mysqldump -h 主机IP -uroot -p db1 db2 db3 >/usr/db123.sql
  • 备份单个数据库
mysqldump -h 主机IP -uroot -p db >/usr/db.sql

2.备份数据库表

  • 备份多张表
mysqldump -h 主机IP -uroot -p db table1  table2 >/data/db_table12.sql
  • 备份单张表
mysqldump -h 主机IP -uroot -p db table   >/data/db_table.sql
  • 备份表时用 where 筛选
mysqldump -h 主机IP -uroot -p db table  --where " 查询条件" >/data/db_table.sql

还原

  • mysqldump命令还原
mysqldump -h 主机IP -uroot -p db < /root/db.sql
  • source命令
source /root/db.sql

实现

这里的话前后端是用的若依框架那一套,vue(elmentui)+springboot 实现。

后端

1.备份工具类

先写一个工具类方便调用,因为我前端的想法是把那些数据表的表名都传过来,所以我就留了个表名的参数。改的时候可以根据你传的数据改参数

public class MySQLDatabaseBackupUtils {
    /**
     * 备份数据库某些表
     *
     *  host IP地址
     * userName 数据库的用户名
     *  password 数据库的密码
     *  savePath 备份文件的地址
     *  fileName 备份文件名称
     *  databaseName 需要备份的数据库的名称
     *  tableNames 表名如:test1 test2 test3
     *  mysqlBin mysql安装路径 如:E:\mysql-5.7.24-winx64\bin linux下:/usr/mysql/bin
     *  备份成功返回true, 否则返回false
     */
    public static boolean backup(String tableNames,String fileName) {

        String host = "192.168.16.2";
        String userName = "root";
        String password = "root";
      //  String savePath = "D:\\文档\\backupFile";
      //服务器的保存地址
        String savePath = "/usr/backupFile";
        String databaseName = "audit";
        ///usr/local/mysql/bin 安装路径
        String mysqlBin = "/usr/local/mysql/bin";

        File saveFile = new File(savePath);
        if (!saveFile.exists()) {// 如果目录不存在
            saveFile.mkdirs();// 创建文件夹
        }
        if (!savePath.endsWith(File.separator)) {
            savePath = savePath + File.separator;
        }
        //拼接命令行的命令
        // mysqldump --opt --host=localhost --databases backup --tables log_sys sys_user --user=root --password=root --result-file=E:\Sqldata\test.sql --default-character-set=utf8
        StringBuilder cmd = new StringBuilder();
        cmd.append(mysqlBin).append("/mysqldump").append(" --opt")
                .append(" --host=").append(host)
                .append(" --databases ").append(databaseName)
                .append(" --tables ").append(tableNames)
                .append(" --user=").append(userName)
                .append(" --password=").append(password)
                .append(" --result-file=").append(savePath + fileName)
                .append(" --default-character-set=utf8 ");
        try {
            //调用外部执行exe文件的javaAPI
            Process process = Runtime.getRuntime().exec(cmd.toString());
            if (process.waitFor() == 0) {// 0 表示线程正常终止
                return true;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return false;
    }
}

2.备份seviceImpl层

我的前端传过来的是 用户选择的模块 以及 模块所属的表名 ,所以我只需要获取表名传入工具类,在用模块名拼接sql文件后缀就ok了。

    @Override
    public boolean backupModule(List<SysDataBackupTable> sysDataBackupTable) {
        List<String> list = sysDataBackupTable.stream().map(SysDataBackupTable::getTableName).collect(Collectors.toList());
        String tableNames = String.join(" ", list);
        //获取模块名
        List<String> collect = sysDataBackupTable.stream().map(SysDataBackupTable::getTableModule).collect(Collectors.toList());
        String s = collect.get(0);
        String moduleName = s + ".sql";
        //调用备份工具类
        boolean backup = MySQLDatabaseBackupUtils.backup(tableNames, moduleName);
        return backup;
    }

还原

1.还原工具类

还原和备份差不多,不过要注意的是 要在linux 上面执行命令的话要加特殊的指令。
还有要注意的是 mysql -u 用户名 -p密码 。这里-p后面与密码直接不能有空格,否则会把你的密码当作数据库名

"/bin/bash","-c"
public class LinuxSqlImportUtils {
    public static boolean exportSql(String fileName){
        String user = "root";
        //mysql -u forceview -pforceview 不能有空格,所以这样写
        String password = "root";
        String host = "192.168.16.2";
        String exportDatabaseName = "audit";

        String exportPath = "/usr/backupFile";

        StringBuilder cmd = new StringBuilder();
        cmd.append("mysql")
                .append(" -u ")
                .append(user)
                .append(" -p")
                .append(password)
                .append(" ")
                .append(exportDatabaseName)
                .append(" < ")
                .append(exportPath)
                .append("/")
                .append(fileName);

        //执行命令
        String[] command = {"/bin/bash","-c",cmd.toString()};

        //使用拼接的方式来完成dos命令
        //windows 用cmd/k
       // String command = new String("cmd /k mysql"+" -h"+host+" -u"+user+" -p"+password+" "+exportDatabaseName+" <"+exportPath+"\\"+fileName);
//        System.out.println(cmd.toString());


        try {
            Process process = Runtime.getRuntime().exec(command);

           if (process.waitFor() == 0){
               return true;
           }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return false;

    }


}

前端

前端我是这样想的,使用一个选择框,选择你想导出的模块,这样选择后就会查出属于某个模块的表,再把表名后模块名传过去;

备份

<el-row >
      <el-form :inline="true" label-width="100px" >
        <el-form-item label="数据备份表">
          <el-select
            v-model="queryParams.tableModule"
            @change="changeSelect()"
            placeholder="请选择模块"
          >
            <el-option
              v-for="item in selectChangeList"
              :key="item.id"
              :label="item.tableModule"
              :value="item.tableModule"
            >
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>
    </el-row>

在这里插入图片描述
比如选择aaa模块进行备份,备份后就会生成一个sql文件在你所指定的路径中,我下面实在window测试的,linux也测试过了。
在这里插入图片描述
在这里插入图片描述
js代码

 //备份按钮
    handleBackupModule(){
      this.$modal.confirm('是否确认备份该模块的表数据?')
      .then(()=>{
         backupModule(this.sysDataBackupList).then(response=>{
          if(response.code == 200){
            this.$message({
              message: "备份成功",
              type: "success"
            });
            this.getFileTable();
          }else{
            this.$message({
              message: "备份失败",
              type: "error"
            });
            this.getFileTable();
          }
      });
      }).catch(()=>{
        this.$message({
              message: "取消备份",
              type: "info"
            });
            this.getFileTable();
      });
    },

还原 及 下载到本地

还原的话就在 查出来的 sql文件 表格后面加一个还原按钮就好,这两个就不详细描述了。

下载到本地的话用的若依自带的download方法。

 //还原
    handleRetoreFile(row){
        this.$modal.confirm('是否确认还原该sql文件?')
        .then(()=>{
         restoreFile(row.fileName).then(res=>{
          if(res.code == 200){
            this.$message({
              message: "还原成功",
              type: "success"
            });
            this.getFileTable();
          }else{
            this.$message({
              message: "还原失败",
              type: "error"
            });
            this.getFileTable();
          }
        });
        }).catch(()=>{
          this.$message({
            message: "取消还原",
            type: "info"
          });
        }) 
    },
 //下载
    handleDownloadFile(row){
      const fileName = row.fileName
      this.download(
        "/dataBackup/downloadFile?fileName=" + fileName,
        {
          ...fileName,
        },
        fileName
      );
    },

下载业务层

@Override
    public boolean downloadFile(String fileName, HttpServletRequest request, HttpServletResponse response) {
        String filePath = path + "/" +fileName;
        File file = new File(filePath);
        response.setCharacterEncoding("UTF-8");
        String realFilename = file.getName();
        response.setHeader("content-type", "application/octet-stream;charset=UTF-8");
        response.setContentType("application/octet-stream;charset=UTF-8");
        if (file.exists()){
            try {
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(realFilename.trim(), "UTF-8"));
                BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file));
                BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
                byte[] bytes = new byte[1024];
                int len;
                while ((len = inputStream.read(bytes,0,bytes.length)) != -1){
                    outputStream.write(bytes,0,len);
                }
                outputStream.close();
                inputStream.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

上传

上传的话用的elmentui 上的上传组件,贴一下前后端

html

 <el-dialog
          title="导入"
          :visible.sync="FileTable.upload.open"
          width="400px"
          append-to-body
        >
          <el-upload
            ref="upload"
            :limit="1"
            accept=".sql"
            :headers="FileTable.upload.headers"
            :action="FileTable.upload.url"
            :disabled="FileTable.upload.isUploading"
            :on-progress="handleFileUploadProgress"
            :on-success="handleFileSuccess"
            :auto-upload="false"
            drag
          >
            <i class="el-icon-upload"></i>
            <div class="el-upload__text">
              将文件拖到此处,或<em>点击上传</em>
            </div>
            <div class="el-upload__tip text-center" slot="tip">
              <div class="el-upload__tip" slot="tip">
                <!-- <el-checkbox v-model="upload.updateSupport" /> 是否更新已经存在的用户数据 -->
              </div>
              <span>仅允许导入sql文件。</span>
              <!-- <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link> -->
            </div>
          </el-upload>
          <div slot="footer" class="dialog-footer">
            <el-button type="primary" @click="submitFile">确 定</el-button>
            <el-button @click="FileTable.upload.open = false">取 消</el-button>
          </div>
        </el-dialog>

data

FileTable: {
 
 // 遮罩层
      loading: true,
      // 选中数组
      ids: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 数据备份表模块表格数据
      FileList: [],
      // 弹出层标题
      title: "",
      // 是否显示弹出层
      open: false,
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        fileName: ""
      },
      // 表单参数
      form: {},
      // 表单校验
      rules: {
      },
      upload: {
        // 是否显示弹出层(用户导入)
        open: false,
        // 弹出层标题(用户导入)
        title: "",
        // 是否禁用上传
        isUploading: false,
        // 是否更新已经存在的用户数据
        // updateSupport: 0,
        // 设置上传的请求头部
        headers: { Authorization: "Bearer " + getToken() },
        // 上传的地址
        url: "https://192.168.16.22/dataBackup/importFile",
      },

js

 //导入
    importFile(){
      this.FileTable.upload.open = true;
    },
     // 文件上传中处理
    handleFileUploadProgress(event, file, fileList) {
      this.FileTable.upload.isUploading = true;
    },
    // 文件上传成功处理
    handleFileSuccess(response, file, fileList) {
      this.FileTable.upload.open = false;
      this.FileTable.upload.isUploading = false;
      this.$refs.upload.clearFiles();
      this.$alert(
        "<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +
          response.msg +
          "</div>",
        "导入结果",
        { dangerouslyUseHTMLString: true }
      );
     this.getFileTable();
    },
  
    // 提交上传文件
    submitFile() {
      this.$refs.upload.submit();
    },

上传的业务层

  @Override
    public boolean importFile(MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            String name = file.getOriginalFilename();
            String newPath = path + "/" + name;
            File uploadFile = new File(newPath);
            byte[] buffer = new byte[2048];
            int len = 0;
            FileOutputStream outputStream = new FileOutputStream(uploadFile);
            while ((len = inputStream.read(buffer)) != -1){
                outputStream.write(buffer,0,len);
            }
            outputStream.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return true;
    }

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

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

相关文章

攻防世界-baigeiRSA

1.下载附件&#xff0c;得到压缩包&#xff0c;解压得到两个文件。 import libnum from Crypto.Util import number from secret import flagsize 128 e 65537 p number.getPrime(size) q number.getPrime(size) n p*qm libnum.s2n(flag) c pow(m, e, n)print(n %d % …

(已更新)Discuz手机模板:NVBING5-APP手机版,界面美观大方,可封装安卓/苹果APP,模板文件+插件+分类信息导入文件

Discuz手机模板&#xff1a;NVBING5-APP手机版——是一款界面美观大方的完整Discuz手机模板&#xff0c;附带模板插件分类信息导入文件详细的安装说明模块说明。 功能介绍 *支持封装安卓APP、苹果APP&#xff0c;原生微信登录、分享等几十项功能 *支持视频上传至优酷云或本地…

水溶性荧光团磺酸基-花青素Cy7 酪酰胺,Tyramide-Sulfo-Cy7

磺酸基-花青素Cy7 酪酰胺是一种水溶性荧光团&#xff0c;用于近红外光谱部分。由于其结构中存在三亚甲基桥&#xff0c;使其量子产率比其他七甲基菁高。氟化染料是理想的体内成像应用。一个非氟化版本&#xff0c;Cyanine7&#xff0c;也可用。 『英文名称』&#xff1a;Tyram…

基础SQL语法语句大全(一篇学会所有SQL语句)

如&#xff1a;select distinct name from student; 如&#xff1a;select name,salary from employee where deptno 3; 如&#xff1a;select * from employees where deptno 3 and salary>-5000;(两个条件同时满足) select * from employees where (deptno 3 or depton…

HARDiNFO Pro 8.0 绿色版-轻便版

HARDiNFO 一体化系统信息、诊断和基准测试 主要特点 硬件清单、计算机管理、基准测试和网络监控 硬件库存 获取有关您的 PC 硬件组件和外围设备的详细系统信息&#xff0c;例如&#xff1b;CPU、内存、主板、显示适配器、HDD/SSD 磁盘驱动器、显示器、笔记本电池、操作系统驱动…

[附源码]JAVA毕业设计医院门诊挂号系统(系统+LW)

[附源码]JAVA毕业设计医院门诊挂号系统&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术…

【QT 5 学习笔记-学习绘图相关+画线图形等+绘图事件+基础学习(1)】

【QT 5 学习笔记-学习绘图相关画线图形等绘图事件基础学习&#xff08;1&#xff09;】1、说明2、实验环境3、参照学习链接4、自己的学习与理解5、学习与实践代码。&#xff08;1&#xff09;建立基础工程。&#xff08;2&#xff09;加入绘图事件与包含库&#xff08;3&#x…

自然语言处理(NLP)数据集汇总 2(附下载链接)

&#x1f384;&#x1f384;【自然语言处理NLP】简介 &#x1f384;&#x1f384; 自然语言处理(Natural Language Processing, NLP)是计算机科学领域与人工智能领域中的一个重要方向。它研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。自然语言处理是一门…

真是绝了!git标星9K

能力f&#xff08;认知&#xff0c;洞察&#xff0c;实践&#xff0c;经验总结&#xff09; 不知道你到了哪个阶段了呢&#xff1f; 架构是软件工程的实践艺术&#xff0c;要化理想为现实&#xff0c;不是空中楼阁。懂得再多的设计理念、方法论&#xff0c;光说不练还是假把式…

大二学生《Web编程基础》期末网页制作 HTML+CSS个人网页设计实例

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

8年前端带你HTML+CSS入门到实战(附视频+源码)

本文主要是解决&#xff1a; ☆ 想要自学前端开发&#xff0c; ☆ 但又不太想看博客文章&#xff0c; ☆ 觉得自学有点吃力&#xff0c;有点不知道学习步骤的同学 目录 一、HTML 1、需要了解熟练的标签 2、不太常用的标签 3、怎么算是HTML学好了&#xff0c;可以继续学CSS了…

ChatGPT教你面试阿里P6测试开发岗

​持续坚持原创输出&#xff0c;点击蓝字关注我吧 最近ChatGPT爆火&#xff0c;ChatGPT能干什么呢&#xff1f;想必已经看过很多文章了&#xff0c;例如ChatGPT通过美国高考、ChatGPT开发游戏、调试代码、写文章等等。 哈哈&#xff0c;作为一个软件测试博主&#xff0c;我怎么…

Java和MySQL的连接和操作(JDBC)

一、数据库的连接 1. 引入JDBC驱动程序 1.1 如何获取驱动程序 驱动程序由数据库提供商提供下载。 MySQL 的驱动下载地址&#xff1a;http://dev.mysql.com/downloads/ 依次点击 Connector/J -> Platform Independent &#xff0c;如然后下载下面那个 1.2 如何在Java …

ADI Blackfin DSP处理器-BF533的开发详解25:LCD_ZIKU(字库在液晶屏上的应用)(含源代码)

硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 功能介绍 代码实现了将字库信息显示到液晶屏上。 代码使用说明 增加了液晶屏驱动&#xff0c;将内存数据显示到液晶屏上。 内存数据转换&…

[附源码]Python计算机毕业设计大学生兼职推荐系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

Git从入门到实战

Git从入门到实战 一、Git概述 1.1、Git简介 Git是一个分布式版本控制工具&#xff0c;通常用来对软件开发过程中的源代码文件进行管理。Git仓库来存储和管理这些文件&#xff0c;Git仓库分为两种&#xff1a; 本地仓库&#xff1a;开发人员自己电脑上的Git仓库远程仓库&…

微服务框架 SpringCloud微服务架构 微服务保护 32 隔离和降级 32.1 Feign整合Sentinel

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 微服务保护 文章目录微服务框架微服务保护32 隔离和降级32.1 Feign整合Sentinel32.1.1 隔离和降级32.1.2 Feign 整合Sentinel32.1.3 总结32 …

算法设计与分析期末复习(一)

算法的定义和特征 什么是算法&#xff1f; 算法是求解某一特定问题的一组有穷规则的集合&#xff0c;它是由若干条指令组成的有穷符号串。算法的五个重要特性 确定性&#xff1a;算法中每一条指令必须有确切的含义&#xff0c;不存在二义性。只有一个入口和一个出口。 可行性&…

raft协议详解

文章目录1. 分布式系统数据一致性概述2. rafts算法基础2.1 基础2.2leader选举2.3raft算法数据同步2.4 raft算法之脑裂2.5 leader宕机处理raft 动画演示1. 分布式系统数据一致性概述 redis保证了可用性&#xff0c;牺牲了一致性 2. rafts算法基础 2.1 基础 2.2leader选举 2.3r…

Python列表(list)反序的7种方法

Python列表(list)原址反序的方法 (本文获得CSDN质量评分【x】)【学习的细节是欢悦的历程】Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅是基础那么简单…… 自学并不是什么神秘的东西&a…