时隔一年多再次回顾数据库数据导出,在这里对博文做一个完善,以及所遇到的问题。
并附上我最近的demo地址:myGithub
完善要点:
1. 对相关DOS命令进行完善以及应用
2. 对dbTask类中添加相应注释
3. 添加dbTask类中的JdbcBean对象实体
4. 添加数据导入数据库的业务方法
注:更新处统一加“//实例20200509” 注释标记
做一个定时任务,每天凌晨备份一下MySQL数据库数据到指定目录。
在网上查了很多资料,最后终于搞出来了,网上查了都是通过DOS命令来导出MySQL数据库数据的;
dos命令执行导出备份命令格式:
mysqldump -P port -h ip -u username -ppassWord dbName > d:\db.sql
//实例20200509
D:\softwares\mysql\mysql-8.0.18-winx64\bin>mysqldump -P 3306 -h 127.0.0.1 -u root -proot demo > d:\data\peng\dbfiles\demo_db1.sql
//实例20200509
dos命令执行数据导入数据库命令格式:
要注意的是该命令必须在MySQL数据库安装目录下bin下执行。因此数据库必须要安装才行。
说来无奈,这项目服务器上原来没有装数据库,导致一直不行,最后装了个才搞好了。。。
好了,进入正题:在项目中首先要引入定时任务,【对了,提前说下我这个项目用springboot框架,因此有很多都是注解,也是meavn项目;】
1.在项目启动类上加注解@EnableScheduling——表示启用定时任务。
package com.zhang;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Import;
import org.springframework.scheduling.annotation.EnableScheduling;
import com.zhang.datasources.DynamicDataSourceConfig;
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
@Import({DynamicDataSourceConfig.class})
@EnableScheduling//启用定时任务注解**************************************************************
public class ZhangApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(ZhangApplication .class, args);
System.out.println("运行完毕!!!!");
System.out.println("启动");
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(ZhangApplication .class);
}
}
//实例20200509
2.在要调用的方法上加注解
@Scheduled(cron="59 59 23 * * ? ") //表示每天晚上23点59分59秒执行一次 其中表达式cron来设置定时任务的时间
附上定时任务时间设置链接:https://www.cnblogs.com/thomas12112406/p/6183946.html
这里当时写的是@Scheduled(cron="0 0 24 * * ? ") ,最后上传服务器,发现项目都无法部署了,报这个表达式格式错误,最后网上一查才知道,这个格式的确错了,就没有零晨24点的写法,无奈之下,直接改为@Scheduled(cron="59 59 23 * * ? ") ,最后测试成功。
//实例20200509
3.JdbcBean.java对象
package com.zhang.demo.job.entity;
/**
* 数据库信息
* @author zhang
* @date 2020-05-08 15:56:00
*/
public class JdbcBean {
private String ip;
private String db;
private int port;
private String username;
private String password;
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getDb() {
return db;
}
public void setDb(String db) {
this.db = db;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
4. 编写数据备份/数据导入业务DbTask.java
//实例20200509
package com.zhang.demo.job.task;
import com.zhang.demo.common.CommonResult;
import com.zhang.demo.job.entity.JdbcBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.RestController;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
/**
* @author zhang
* @date 2020-05-08 15:56:00
*/
@RestController
public class DbTask {
public static final String WINDOWS_UPLOAD_PATH = "D:/data/peng/dbfiles/";
public static final String LINUX_UPLOAD_PATH = "/data/peng/dbfiles/";
public static final String SQL_BACKUP_PREFIX_FORMAT = "yyyyMMddHHmmss";
private Logger logger = LoggerFactory.getLogger(getClass());
static String filePath;
/**
* 数据库备份 导出.sql文件到本地
* @return
*/
@Scheduled(cron="59 59 23 * * ? ")//表示每天晚上23点59分59秒执行一次
public CommonResult backup(){
try {
String fileName = new SimpleDateFormat(SQL_BACKUP_PREFIX_FORMAT).format(new Date())+"_backup";
filePath = getFilePath(fileName+".sql");
/*
* 动态获取数据库配置
*/
JdbcBean j = new JdbcBean();
Properties prop = new Properties();//读取properties 文件所用的类
try {
InputStream in = DbTask.class.getResourceAsStream("/application.properties");
// InputStream in = DbTask.class.getResourceAsStream("/application.yml");
prop.load(in); // /加载属性列表
String [] a = prop.getProperty("spring.datasource.druid.first.url").split("/");
j.setIp(a[2].split(":")[0]);
j.setDb(a[3].trim().split("[?]")[0]);
j.setPort(Integer.parseInt(a[2].split(":")[1]));
j.setUsername(prop.getProperty("spring.datasource.druid.first.username"));
j.setPassword(prop.getProperty("spring.datasource.druid.first.password"));
in.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
boolean exportFlag = executeExportCommond(j,filePath);
if(exportFlag){
logger.info("数据库数据备份本地成功!");
return CommonResult.success("数据库数据备份本地成功!");
}else{
logger.info("数据库数据备份失败");
return CommonResult.failed("数据库数据备份失败");
}
} catch (Exception e) {
logger.info("运行异常,数据库数据备份失败!");
e.printStackTrace();
return CommonResult.failed("备份失败");
}
}
/**
* 导出数据
* dos命令执行备份 mysqldump -P port -h ip -u username -ppassword dbName > d:\db.sql
* (注意命令中-ppassWord ———— -p和密码之间不能有空格(导出命令中未输入密码的跳过该错),
* 否则会提示输入密码,输入之后回车会报错【报错信息:
* mysqldump: Got error: 1049: Unknown database 'root' when selecting the database】)
* DOS命令如下:
* D:\softwares\mysql\mysql-8.0.18-winx64\bin>
* mysqldump -P 3306 -h 127.0.0.1 -u root -proot demo > d:\data\peng\dbfiles\demo_db.sql
* @param jdbcBean
* @param filePath
* @return
* @throws IOException
* @throws InterruptedException
*/
//执行导出命令
public static boolean executeExportCommond(JdbcBean jdbcBean,String filePath) throws IOException, InterruptedException{
//动态获取本地MySQL数据库安装目录bin下的目录
String C=getMysqlPath();
//静态获取本地MySQL数据库安装目录下bin的目录
// String C="C:\\Program Files\\MySQL\\MySQL Server 5.6\\bin\\";
String sql ="mysqldump -P "+jdbcBean.getPort()+" -h "+jdbcBean.getIp()+
" -u "+jdbcBean.getUsername()+" -p"+jdbcBean.getPassword()+
" "+jdbcBean.getDb()+" --default-character-set=utf8 "+
"--lock-tables=false --result-file="+filePath;
System.out.println(sql);
Process process = Runtime.getRuntime().exec(sql);
if(process.waitFor()==0){//0 表示线程正常终止。
return true;
}
return false;//异常终止
}
/**
* 导入指定sql文件数据到指定数据库
* sql_1 ———— 表示登录mysql数据库中。命令:mysql -P 3306 -h localhost -u root -proot --default-character-set=utf8
* sql_2 ———— 表示使用mysql数据库中的哪一个数据库。命令:use test
* sql_3 ———— 表示执行导入该路径下的sql文件。命令:source d:\data\peng\dbfiles\demo_db1.sql
*
* @date 2020-05-09 09:56:56
* @param jdbcBean
* @param filePath
* @return
* @throws Exception
*/
//执行导入命令
public static boolean executeImportCommond(JdbcBean jdbcBean,String filePath) throws Exception {
//动态获取本地MySQL数据库安装目录bin下的目录
String C=getMysqlPath();
//静态获取本地MySQL数据库安装目录下bin的目录
// String C="C:\\Program Files\\MySQL\\MySQL Server 5.6\\bin\\";
String sql_1 ="mysql -P "+jdbcBean.getPort()+" -h "+jdbcBean.getIp()+
" -u "+jdbcBean.getUsername()+" -p"+jdbcBean.getPassword()+
" --default-character-set=utf8";
String sql_2 = "use "+jdbcBean.getDb();
String sql_3 = "source "+filePath;
Process process = Runtime.getRuntime().exec(sql_1);
OutputStream os = process.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(os);
writer.write(sql_2 + "\r\n" + sql_3);
writer.flush();
writer.close();
os.close();
if(process.waitFor()==0){
return true;
}
return false;
}
/**
* 动态获取mysql安装路径(bin下的路径)
*【注】:本地MySQL数据库配置环境变量(新建MYSQL_HOME变量,值为“MySQL安装路径下【bin的上一层】”,
* 在Path变量中配置MYSQL_HOME变量,值为【%MYSQL_HOME%bin】)。
* @return
*/
public static String getMysqlPath(){
@SuppressWarnings("rawtypes")
Map m=System.getenv();
String s2=(String) m.get("MYSQL_HOME");//获取本计算机环境变量中PATH的内容
String mySqlPath=s2+"\\bin\\";
System.out.println("MySQL本地安装路径:"+mySqlPath);
return mySqlPath;
}
/**
* 获得文件路径
* @param fileName
* @return
*/
public static String getFilePath(String fileName){
String os = System.getProperty("os.name"); //获取操作系统的名称
String rootPath;
String filPath;
if(os.toLowerCase().startsWith("win") || os.toLowerCase().startsWith("Win")){
rootPath = WINDOWS_UPLOAD_PATH;
}else{
rootPath = LINUX_UPLOAD_PATH;
}
if(!new File(rootPath).exists()){//判断文件是否存在
new File(rootPath).mkdirs();//可以在不存在的目录中创建文件夹。诸如:a\\b,既可以创建多级目录。
}
if(fileName==null){
filPath = rootPath+new SimpleDateFormat(SQL_BACKUP_PREFIX_FORMAT).format(new Date())+"_backup.sql";
}else{
filPath = rootPath+fileName;
}
return filPath;
}
}
5.直接启动项目,然后就根据你设置的时间来进行调用这个方法。
【这目前只是导出MySQL数据库的Java写法,导入还没整出来,欢迎大神们指点一二,我会再接再励的】