今天在做毕设的最后一个模块,数据库的备份和还原。按照拿来主义的惯例,先百度一下,找找资料,很快就搞定了数据库的备份,但还原却总是出问题,最后还是搞定,在此写下记录,希望对大家有帮助。
至于备份还原数据库,肯定少不了一些基本的配置信息,如数据库的主机地址啦(host)、端口啦(port)、还有用户名、密码,以及你要操作的那个数据库的名称、存放备份文件(*.sql文件)的路径等等。
这些信息我在Spring中配置好了,如下:
<!-- 用于读取数据库的基本信息 -->
<bean id="dataInfo"
class="com.shutao.hr.assist.DBInfo">
<property name="dbName" value="hr"/>
<property name="username" value="root"/>
<property name="password" value="shutao"/>
<property name="host" value="127.0.0.1"/>
<property name="port" value="3306"/>
<property name="dbToolsPath" value="D:/MySQL/MySQL Server 5.1/bin/"/>
<property name="tablesPath" value="F:/hr/hr_tables/"/>
<property name="databasePath" value="F:/hr/hr_database/"/>
</bean>
然后新建一个用来操作数据库备份还原的类:DBManager。
第一步要做的当然就是读取配置信息,如下是该类的一部分代码:
static String dbName = "";
static String username = "";
static String password = "";
static String host = "";
static String port = "";
static String dbToolsPath = "";
static String databasePath = "";
static String tablesPath = "";
static String filePath = ""; //备份文件的路径
static ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
static {
DBInfo dbInfo = (DBInfo) context.getBean("dataInfo");
dbName = dbInfo.getDbName();
username = dbInfo.getUsername();
password = dbInfo.getPassword();
host = dbInfo.getHost();
port = dbInfo.getPort();
dbToolsPath = dbInfo.getDbToolsPath();
databasePath = dbInfo.getDatabasePath();
tablesPath = dbInfo.getTablesPath();
}
生成用于备份数据库的shell命令类:
/**
* 生成用于备份数据库的shell命令
* @param
* targetName 要备份的对象名:只能为表名和数据库名称
* @return 实际执行的shell命令
*/
public static String getBackupShellString(String targetName) {
String basepath = Thread.currentThread().getContextClassLoader().getResource("").toString();
String database_tools_path = dbToolsPath;
//备份的文件
String backFilePath = "";
// 若要备份整个数据库
if (targetName.equals(dbName)) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
// 要备份的文件
backFilePath = databasePath + targetName + "_"+ sdf.format(new Date()) + ".sql";
targetName = "";
} else {
backFilePath = tablesPath + targetName + ".sql";
}
// 判断要备份的文件/文件夹是否已存在
File backFileFolder_db = new File(databasePath);
File backFileFolder_tab = new File(tablesPath);
if (!backFileFolder_db.exists()) {
backFileFolder_db.mkdirs();
}
if (!backFileFolder_tab.exists()) {
backFileFolder_tab.mkdirs();
}
String OSType = System.getProperty("os.name");
String shellStr = "";
shellStr = database_tools_path + "mysqldump -h " + host
+ " -P " + port + " -u " + username + " -p" //★第二个-p后面不能有空格,否则将被认为是数据库的名称
+ password + " --result-file=" + backFilePath
+ " --default-character-set=gbk " + dbName + " "
+ targetName;
System.out.print("##############" + shellStr);
return shellStr;
}
进行备份操作的类:
/**
* 备份数据库
* @param
* targetName 要备份的对象名:只能为表名和数据库名称
* @return 成功:TRUE 失败:FALSE
*
*/
public static boolean backup(String targetName) {
Runtime runt = Runtime.getRuntime();
Process proc;
try {
proc = runt.exec(getBackupShellString(targetName));
int tag = proc.waitFor();// 等待进程终止
if (tag == 0) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
///还原数据库/
public static void restoreDB(String targetName) {
//要读取的备份文件的路径
String fPath="";
try {
if(targetName.equals(dbName)){
//这里用于测试,先指定一个数据库文件,实际应用中应根据选择来确定文件名称
fPath = databasePath+"hr_20110415161235.sql";
}else{
fPath = tablesPath+targetName+".sql";
}
System.out.println("fPath:"+fPath);
Runtime rt = Runtime.getRuntime();
// 调用 mysql 的 cmd:
Process child = rt.exec(dbToolsPath+"mysql -uroot -pshutao "+dbName);
// int tag = child.waitFor();
OutputStream out = child.getOutputStream();//控制台的输入信息作为输出流
String inStr;
StringBuffer sb = new StringBuffer("");
String outStr;
//下面的InputStreamReader和OutputStreamWriter的第二个参数为数据的编码格式,
// 注意要跟备份的格式一样,否则会有异常:java.io.IOException: 管道已结束。
BufferedReader br=new BufferedReader(new InputStreamReader( new FileInputStream(fPath), "gbk"));
while ((inStr = br.readLine()) != null) {
sb.append(inStr + "/r/n");
}
outStr = sb.toString();
OutputStreamWriter writer = new OutputStreamWriter(out, "gbk");
writer.write(outStr);
writer.flush();
// 别忘记关闭输入输出流
out.close();
br.close();
writer.close();
System.out.println("/* Load OK! */");
} catch (Exception e) {
e.printStackTrace();
}
}
上面的几个方法经过测试都可以运行。
还原的时候切记注意那个编码格式,一开始用的是utf8,一直出现那个管道已结束的异常.......
一开始用的是直接用Mysql的命令来还原,但一直不成功,命令倒是可以执行,如下:
/**
* 根据路径生成恢复数据库的Shell字符串
* @param targetName 要还原的对象名:只能为表名和数据库名称
* @return 恢复数据时实际执行的shell
*/
public static String getRestoreShellString(String targetName) {
String database_tools_path = dbToolsPath;
String backFile = "";// 已备份的文件
if (targetName.indexOf(dbName) == -1) {// 还原表
backFile = tablesPath + targetName + ".sql";
} else {// 还原库
backFile = databasePath + targetName;
}
String shellStr = "";
shellStr = database_tools_path + "mysql -h" + host + " -P"
+ port + " -u" + username + " -p"
+ password + " --default-character-set=gbk "
+ dbName + " < " + backFile;
return shellStr;
}
/**
* 恢复数据库
* @param targetName 要备份的对象名:只能为表名和数据库名称
* @return 成功:TRUE 失败:FALSE
*/
public static boolean restore(String targetName) {
try {
Runtime runt = Runtime.getRuntime();
Process proc ;
String cmdtext = getRestoreShellString(targetName);
if (System.getProperty("os.name").indexOf("Windows") != -1) {
String[] cmd = { "cmd", "/c", cmdtext };
proc = runt.exec(cmd);
} else {
String[] cmd = { "sh", "-c", cmdtext };
proc = runt.exec(cmd);
}
System.out.println("cmdtext: "+cmdtext);
int tag = proc.waitFor();// 等待进程终止
System.out.println("进程返回值为tag:" + tag);
if (tag == 0) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
具体原因暂且不去研究了,还有其他事情要做了~~乖乖用第一中读取文件流的方法吧。