springboot項(xiàng)目實(shí)現(xiàn)定時(shí)備份數(shù)據(jù)庫(kù)導(dǎo)出sql文件方式
之所以做這個(gè)功能的原因是我的服務(wù)器上的數(shù)據(jù)庫(kù)被攻擊了,還好服務(wù)器上沒(méi)有什么重要的數(shù)據(jù),但是數(shù)據(jù)沒(méi)了就很肉疼,因此做了這個(gè)功能,用來(lái)定時(shí)備份數(shù)據(jù)庫(kù)數(shù)據(jù)
添加依賴(lài)
這里用到了 hutool 工具包 這個(gè)包挺好用的,推薦大家可以多看看他的官方文檔
官方文檔:https://www.hutool.cn/docs/#/
<!-- hutool工具類(lèi)-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.3</version>
</dependency>添加配置文件和配置
因?yàn)檫@里只是需要導(dǎo)出sql 所以就使用了hutool工具中的DB
在resources目錄下創(chuàng)建db.setting數(shù)據(jù)庫(kù)配置文件
文件中內(nèi)容:
## url 數(shù)據(jù)庫(kù)連接地址 ## user 連接數(shù)據(jù)庫(kù)賬號(hào) ## pass 連接數(shù)據(jù)庫(kù)密碼 url = jdbc:mysql://localhost:3306/test user = root pass = 123456
緊接著在application.yml文件中添加sql文件的存放的路徑
# 導(dǎo)出sql文件的位置 sql: dbname: notepad # 數(shù)據(jù)庫(kù)名 filePath: /data/sql/ # 導(dǎo)出sql文件的位置 win下會(huì)直接在項(xiàng)目所在磁盤(pán)下建立 data/sql文件
編寫(xiě)導(dǎo)出SQL的方法
方法直接貼在下面:
package com.an.notepad.task;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.db.ds.DSFactory;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.experimental.Accessors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.io.File;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.util.List;
@Configuration
public class ExportSQL {
// 用于打印執(zhí)行日志
private static final Logger logger = LoggerFactory.getLogger(ExportSQL.class);
// 存儲(chǔ)的路徑
@Value("${sql.filePath}")
private String filePath;
// 數(shù)據(jù)庫(kù)名
@Value("${sql.dbname}")
private String database_name;
// 需要導(dǎo)出的表名
private final List<TempBean> tempBeanList = CollectionUtil.newArrayList(
// 這里寫(xiě)需要存儲(chǔ)的表名 有幾張表就new幾個(gè)
new TempBean().setTable("n_note"),
new TempBean().setTable("n_user")
);
@SneakyThrows
public void export() {
//獲取默認(rèn)數(shù)據(jù)源
DataSource ds = DSFactory.get();
// 獲取數(shù)據(jù)庫(kù)連接對(duì)象
Connection connection = ds.getConnection();
// 獲取連接信息
DatabaseMetaData metaData = connection.getMetaData();
// 創(chuàng)建sql文件對(duì)象
FileWriter sqlFileWriter = FileWriter.create(new File(filePath + database_name + ".sql"));
sqlFileWriter.write("");
sqlFileWriter.append("USE " + database_name + ";\n");
sqlFileWriter.append("/*\n");
sqlFileWriter.append(" --------------------------------------------------\n");
sqlFileWriter.append(" Target Server Type : " + metaData.getDatabaseProductName() + ";\n");
sqlFileWriter.append(" Target Server Version : " + metaData.getDatabaseProductVersion() + ";\n");
sqlFileWriter.append(" \n");
sqlFileWriter.append(" Target Server Date : " + DateTime.now() + ";\n");
sqlFileWriter.append(" \n");
sqlFileWriter.append(" --------------------------------------------------\n");
sqlFileWriter.append("*/\n");
sqlFileWriter.append("SET NAMES utf8mb4;\n");
sqlFileWriter.append("SET FOREIGN_KEY_CHECKS = 0;\n");
for (TempBean tempBean : tempBeanList) {
String table = tempBean.table;
sqlFileWriter.append("\n\n\n");
// DROP TABLE
sqlFileWriter.append("DROP TABLE IF EXISTS `" + table + "`;\n");
// CREATE TABLE
Entity createTableEntity = Db.use().queryOne("SHOW CREATE TABLE " + table);
sqlFileWriter.append((String) createTableEntity.get("Create Table"));
sqlFileWriter.append(";\n");
// 看配置,是否需要insert語(yǔ)句
if (!tempBean.insert) {
continue;
}
// INSERT INTO
List<Entity> dataEntityList = Db.use().query("SELECT * FROM " + table);
for (Entity dataEntity : dataEntityList) {
StrBuilder field = StrBuilder.create();
StrBuilder data = StrBuilder.create();
dataEntity.forEach((key, value) -> {
field.append(key).append(", ");
if (ObjectUtil.isNotNull(value)) {
if (StrUtil.equals("true", String.valueOf(value))) {
data.append("b'1'");
} else if (StrUtil.equals("false", String.valueOf(value))) {
data.append("b'0'");
} else {
data.append("'").append(value).append("'");
}
} else {
data.append("NULL");
}
data.append(", ");
});
sqlFileWriter.append("INSERT INTO `" + table + "`(");
String fieldStr = field.subString(0, field.length() - 2);
sqlFileWriter.append(fieldStr);
sqlFileWriter.append(") VALUES (");
String dataStr = data.subString(0, data.length() - 2);
sqlFileWriter.append(dataStr);
sqlFileWriter.append(");\n");
}
}
sqlFileWriter.append("\n\n\n");
sqlFileWriter.append("SET FOREIGN_KEY_CHECKS = 1;\n");
logger.info(">>>>>>>>>> 存儲(chǔ)sql成功" + DateTime.now());
}
@Data
@Accessors(chain = true)
static class TempBean {
// 表名
public String table;
// 是否需要insert語(yǔ)句,默認(rèn)需要 (表中數(shù)據(jù))
public Boolean insert = true;
}
}創(chuàng)建定時(shí)任務(wù)
package com.an.notepad.task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
/**
* 定時(shí)導(dǎo)出數(shù)據(jù)庫(kù)sql功能
*/
@Configuration
@EnableScheduling // 開(kāi)啟定時(shí)任務(wù)
public class ExportTask {
@Autowired
private ExportSQL exportSQL;
//@Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1點(diǎn)觸發(fā)一次
@Scheduled(cron = "*/5 * * * * ?") // 5秒觸發(fā)一次
public void task() {
exportSQL.export();
}
}
編寫(xiě)完成 運(yùn)行測(cè)試一下

我這里項(xiàng)目在D盤(pán)中,因此D盤(pán)下D:\data\sql 默認(rèn)會(huì)有生成的文件


成功,我這邊測(cè)試了一下,數(shù)據(jù)庫(kù)是可以導(dǎo)入的
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
springboot-dubbo cannot be cast to問(wèn)題及解決
這篇文章主要介紹了springboot-dubbo cannot be cast to問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
解決Mybatis返回update后影響的行數(shù)問(wèn)題
這篇文章主要介紹了解決Mybatis返回update后影響的行數(shù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11
Java OpenCV實(shí)現(xiàn)圖像鏡像翻轉(zhuǎn)效果
這篇文章主要為大家詳細(xì)介紹了Java OpenCV實(shí)現(xiàn)圖像鏡像翻轉(zhuǎn)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07
JDK8的lambda方式List轉(zhuǎn)Map的操作方法
account是一個(gè)返回本身的lambda表達(dá)式,其實(shí)還可以使用Function接口中的一個(gè)默認(rèn)方法代替,使整個(gè)方法更簡(jiǎn)潔優(yōu)雅,這篇文章主要介紹了JDK8的lambda方式List轉(zhuǎn)Map,需要的朋友可以參考下2022-07-07
Java設(shè)計(jì)模式之原型模式詳細(xì)解讀
這篇文章主要介紹了Java設(shè)計(jì)模式之原型模式詳細(xì)解讀,原型模式屬于創(chuàng)建型設(shè)計(jì)模式,用于創(chuàng)建重復(fù)的對(duì)象,且同時(shí)又保證了性能,該設(shè)計(jì)模式的好處是將對(duì)象的創(chuàng)建與調(diào)用方分離,需要的朋友可以參考下2023-12-12
Java 創(chuàng)建URL的常見(jiàn)問(wèn)題及解決方案
這篇文章主要介紹了Java 創(chuàng)建URL的常見(jiàn)問(wèn)題及解決方案的相關(guān)資料,需要的朋友可以參考下2016-10-10

