Java實現SQLserver數據的備份與還原


由於項目需求,最近用到了在系統中給用戶提供數據備份與還原功能,數據庫為SQLserver2005,第一次遇到這種需求,做的過程也遇到了不少問題,特此記錄下來,以備不時之需,同時也供有類似需求的童鞋借鑒,或者有啥好的方案,也可以拿出來大家一起交流嘛。

代碼如下:

 

1.數據庫工具類用於獲取數據庫連接,執行sql

 1 package com.bhne.web.util;
 2 
 3 import java.io.BufferedInputStream;
 4 import java.io.FileInputStream;
 5 import java.io.IOException;
 6 import java.io.InputStream;
 7 import java.sql.Connection; 
 8 import java.sql.DriverManager; 
 9 import java.sql.SQLException; 
10 import java.util.Properties;
11 
12 import javax.servlet.http.HttpServletRequest;
13 
14 import org.apache.struts2.ServletActionContext;
15 
16 import com.opensymphony.xwork2.ActionContext;
17 
18 
19 public class DataBaseUtil { 
20 /** 
21 * 獲取數據庫連接 
22 * @return Connection 對象 
23 */ 
24 public static Connection getConnection(HttpServletRequest request) { 
25 Properties prop = new Properties(); 
26 Connection conn = null; 
27 try{
28 InputStream in = new BufferedInputStream(new FileInputStream(request.getSession().getServletContext().getRealPath("/")+"dbConfig.properties"));
29 prop.load(in); //加載屬性列表
30 in.close();
31 
32 String url = prop.getProperty("url");
33 String username = prop.getProperty("username");
34 String password = prop.getProperty("password");
35 String driver = prop.getProperty("driver");
36 
37 Class.forName(driver);
38 conn = DriverManager.getConnection(url, username, password); 
39 
40 } catch (ClassNotFoundException e) { 
41 e.printStackTrace(); 
42 } catch (SQLException e) { 
43 e.printStackTrace(); 
44 } catch (IOException e) { 
45 e.printStackTrace(); 
46 } 
47 return conn; 
48 } 
49 
50 public static void closeConn(Connection conn) { 
51 if (conn != null) { 
52 try { 
53 conn.close(); 
54 } catch (SQLException e) { 
55 e.printStackTrace(); 
56 } 
57 } 
58 } 
59 }

 

2. 資源文件(dbConfig.properties),用來配置一些路徑和數據庫配置

#數據庫配置
#url
url=jdbc:sqlserver://GSEIVR8NBYQ0FXO:1433;DatabaseName=master

#驅動程序
driver=com.microsoft.sqlserver.jdbc.SQLServerDriver

#用戶名
username=sa

#密碼
password =admin

#數據庫名稱
dbname=TaskAssignment

#備份還原路徑(該路徑在數據庫服務器下)
back_path=D:/back_path/

 

3.備份

/** 
* 備份數據庫 
* @return backup 
* @throws IOException 
* @throws Exception 
*/ 
@RequestMapping("/backup.call")
public void backup(HttpServletRequest request,HttpServletResponse response) throws IOException { 

Map<String,Object> map = new HashMap<String,Object>();
String message = "數據庫備份失敗";
map.put("success", false);
map.put("message", message);
try {

Properties prop = new Properties();
InputStream in = new BufferedInputStream(new FileInputStream(request.getSession().getServletContext().getRealPath("/")+"dbConfig.properties"));
prop.load(in);
in.close();
String back_path = prop.getProperty("back_path");
String dbname = prop.getProperty("dbname"); //數據庫名 
String name =dbname+ new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()); //文件名
File file = new File(back_path);
String path = file.getPath() + File.separator + name + ".bak";// name文件名 
String str = "backup database "+dbname+" to disk=? with init";

PreparedStatement ps = DataBaseUtil.getConnection(request).prepareStatement(str.toString());
ps.setString(1,path);
boolean bl = ps.execute();
if(!bl){

//將生成的備份文件信息寫入配置文件中
FileOutputStream oFile = new FileOutputStream(request.getSession().getServletContext().getRealPath("/")+"dbConfig.properties");//true表示追加打開
prop.setProperty("back_file", name);

prop.store(oFile, "The New properties file");
oFile.close();
map.put("success", true);
map.put("message", "數據庫備份成功");
JSONObject rt = new JSONObject(map);
response.getWriter().write(rt.toString());

}
} catch (Exception e) {
map.put("success", false);
map.put("message", "數據庫備份異常");
JSONObject rt = new JSONObject(map);
response.getWriter().write(rt.toString());
e.printStackTrace(); 
}

}

 

5.還原(需要調用一個存儲過程)

/** 
* 數據庫還原 
* @return recovery 
* @throws IOException 
*/
@RequestMapping("/recovery.call")
public void recovery(HttpServletRequest request,HttpServletResponse response) throws IOException { 

Map<String,Object> map = new HashMap<String,Object>();
map.put("success", false);
map.put("message", "數據庫還原失敗");
try {

Properties prop = new Properties();
InputStream in = new BufferedInputStream(new FileInputStream(request.getSession().getServletContext().getRealPath("/")+"dbConfig.properties"));
prop.load(in);
in.close();

String dbname = prop.getProperty("dbname"); //數據庫名 

//備份文件路徑
String name = prop.getProperty("back_file");
String back_path = prop.getProperty("back_path");
File file= new File(back_path);
String path = file.getPath()+File.separator+name+".bak";


//恢復所有連接 sql
String recoverySql = "alter database "+dbname+" set online with rollback immediate"; 

StringBuffer restoreSql = new StringBuffer();
restoreSql.append("RESTORE DATABASE ").append(dbname);
restoreSql.append(" FROM DISK=N'").append(path).append("'");
restoreSql.append(" WITH REPLACE,FILE = 1,RECOVERY,STATS = 5");

PreparedStatement ps = DataBaseUtil.getConnection(request).prepareStatement(recoverySql);
PreparedStatement rs = DataBaseUtil.getConnection(request).prepareStatement(restoreSql.toString());
CallableStatement cs = DataBaseUtil.getConnection(request).prepareCall("{call killrestore(?,?)}");

cs.setString(1, dbname); // 數據庫名 
cs.setString(2, "'"+path+"'"); // 已備份數據庫所在路徑 
boolean bl = cs.execute(); // 關閉數據庫鏈接進程
boolean flg = rs.execute();

boolean recoverFlg = ps.execute(); // 恢復數據庫連接

if((!bl)&&(!recoverFlg)&&(!flg)){
map.put("success", true);
map.put("message", "數據庫還原成功");
} 
} catch (Exception e) { 

e.printStackTrace(); 
} 
JSONObject rt = new JSONObject(map);

response.getWriter().write(rt.toString());
}

 

 

6.存儲過程(需放入mster數據庫中)

CREATE proc killrestore (@dbname varchar(20),@dbpath varchar(40)) 
as 
begin 
declare @sql nvarchar(500) 
declare @spid int 
set @sql='declare getspid cursor for select spid from sys.sysprocesses where dbid=db_id('''+@dbname+''')' 
exec (@sql) 
open getspid 
fetch next from getspid into @spid 
while @@fetch_status <> -1 
begin 
exec('kill '+@spid) 
fetch next from getspid into @spid 
end 
close getspid 
deallocate getspid 
end

 

全部代碼供上。

 

注意事項:

        1.執行數據庫備份時,生成的數據庫備份文件會保存在數據庫服務器所在的機器中,而不是客戶機中。

        2.還原功能,大多數項目開發都是使用框架來搞的,很多人估計很疑惑,為啥還單獨寫一個jdbc工具類呢,是這樣的,在執行數據還原之前,首先要關閉數據鏈接,調用的那個存儲過程就是用來殺死進程的,如果使用系統鏈接的那個數據庫來操作的話,會出現【不能kill自己的進程】,所有通過master數據鏈接來進行操作就可以避免這個問題了。

        3.原作者在通過存儲過程進行數據還原的,但是不知道啥原因,存儲過程執行的時候老是報【系統錯誤2】並且路徑也不正確,所有我就把還原的命令拿出來單獨執行了。

      

 

 

參考鏈接:http://blog.csdn.net/tkd03072010/article/details/6668940

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM