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

7 篇文章 1 订阅

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;
    }
  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
Java,可以使用达梦数据库提供的备份还原方法来进行数据库备份。根据引用\[1\]和引用\[2\]的内容,有以下几种备份还原方法可供选择: 方法一:最简单最稳妥的数据备份还原方法 1. 停止"DmServiceDMSERVER"服务(即冷备)。 2. 复制生产库的"D:\dmdbms\data\DAMENG"文件夹。 3. 将复制的文件夹粘贴到备份服务器的"D:\dmdbms\data"目录下,覆盖原有的"DAMENG"文件夹。 方法二:常规使用的备份还原方法 1. 配置数据库的归档模式,确保数据库处于归档模式下。 2. 使用数据库管理员账户登录数据库,进行备份操作。 方法三:逻辑备份还原 1. 创建用户。 2. 进行全库备份还原,可以导入到自己的账户或其他账户。 3. 进行模式导出和导入。 4. 进行表的导出和导入。 方法四:联机备份还原 1. 进行数据库级别备份还原。 2. 进行表空间级别备份还原。 3. 进行表级别备份还原。 方法五:脱机备份还原 1. 进行数据库级别备份还原。 2. 进行表空间级别备份还原。 3. 进行表级别备份还原。 以上是一些常用的Java达梦数据库备份还原方法,具体使用哪种方法取决于你的需求和环境。 #### 引用[.reference_title] - *1* [DM达梦数据库--备份还原三种方法](https://blog.csdn.net/zfang9528/article/details/106202926)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [9、达梦数据库 备份 还原](https://blog.csdn.net/u013736117/article/details/127324317)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值