【定时导出数据库数据】Java导出mysql数据库数据到本地&导入sql文件数据到mysql数据库——项目总结

前言:

时隔一年多再次回顾数据库数据导出,在这里对博文做一个完善,以及所遇到的问题。

并附上我最近的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命令执行数据导入数据库命令格式: 

【定时导出数据库数据】Java导出mysql数据库数据到本地&导入sql文件数据到mysql数据库——项目总结_第1张图片

要注意的是该命令必须在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

【定时导出数据库数据】Java导出mysql数据库数据到本地&导入sql文件数据到mysql数据库——项目总结_第2张图片

该注解也可以写在定时任务配置类上,自定义一个配置类,添加 @EnableScheduling // 启用定时任务,这样就不用写在启动类上了,已测试OK。如下图:

【定时导出数据库数据】Java导出mysql数据库数据到本地&导入sql文件数据到mysql数据库——项目总结_第3张图片

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写法,导入还没整出来,欢迎大神们指点一二,我会再接再励的】

 

你可能感兴趣的:(定时任务,数据库,所遇问题)