java批量处理数据库语句_Java项目中调用bat批处理进行多用户数据库备份
Java項目中調用bat批處理配合使用BCP進行多用戶數據的備份
一、項目需求
最近項目中需要對數據庫(Sql Server系列數據庫)進行備份。項目中的需求不是簡單的整個數據庫的備份,而是根據用戶來備份,具體的備份策略如下:
①系統為某一賽事管理類型的系統,整個系統分為幾部分,前半部分的處理是在服務器上處理,后半部分的處理,是在用戶自己的客戶端中處理。不同的賽事對應不同的用戶,用戶將需要的數據提交給系統進行處理。
②系統在處理完數據之后,用戶可以導出自己賽事相關的數據了,這個導出實際上做的就是個備份數據庫,只不過只備份屬于自己的數據庫。然后下載系統的處理結果,很顯然,各個用戶的數據是不相同的。
③用戶下載自己備份的數據庫文件(這些個文件會打包成zip壓縮包),再導入自己的客戶端系統中。
整個系統使用的關鍵是:程序中調用bcp命令的時候傳遞用戶相關的參數過去就OK了。處理流程如圖1-1所示:
圖1-1 處理流程
二、解決方案
本文提出的是使用Runtime.getRuntime().exec()調用批處理文件,程序中傳遞相關參數給bcp命令。關于BCP命令的詳解,微軟的MSDN上面寫的非常的詳細,在此就不贅述了!下面的一段話引用自微軟的msdn上面的一段介紹:
bcp 實用工具可以在 Microsoft SQL Server 實例和用戶指定格式的數據文件間大容量復制數據。使用 bcp 實用工具可以將大量新行導入 SQL Server 表,或將表數據導出到數據文件。除非與 queryout 選項一起使用,否則使用該實用工具不需要了解 Transact-SQL 知識。若要將數據導入表中,必須使用為該表創建的格式文件,或者必須了解表的結構以及對于該表中的列有效的數據類型。
三、系統的實現
實現主要分為批處理文件的編寫和Java程序中的調用兩部分,這兩部分完成之后,第一部分中的后續問題就好解決了。
①批處理編寫:
編寫的批處理文件如下,也就是使用bcp工具來進行備份
這里只列出部分表,代碼都是一樣的,使用的時候稍微修改下即可!@Title 根據userId導出的表
@bcp "SELECT * FROM sportSys.dbo.competitions wheresportSys.dbo.competitions.userId="+%1 queryout %2competitions.xls -T -c>>%3log.txt
@echo competitions表備份已完成!>>%3log.txt
@bcp "SELECT * FROM sportSys.dbo.item wheresportSys.dbo.item.userId="+%1 queryout %2item.xls -T -c>>%3log.txt
@echo item表備份已完成!>>%3log.txt
@bcp "SELECT * FROM sportSys.dbo.itemType wheresportSys.dbo.itemType.userId="+%1 queryout %2itemType.xls -T -c>>%3log.txt
@echo itemType表備份已完成!>>%3log.txt
@bcp "SELECT * FROM sportSys.dbo.agenda wheresportSys.dbo.agenda.userId="+%1 queryout %2agenda.xls -T -c>>%3log.txt
@echo agenda表備份已完成!>>%3log.txt
@bcp "SELECT * FROM sportSys.dbo.allroundInfo wheresportSys.dbo.allroundInfo.userId="+%1 queryout %2allroundInfo.xls -T -c>>%3log.txt
@echo allroundInfo表備份已完成!>>%3log.txt
@bcp "SELECT * FROM sportSys.dbo.athlete wheresportSys.dbo.athlete.userId="+%1 queryout %2athlete.xls -T -c>>%3log.txt
@echo athlete表備份已完成!>>%3log.txt
@exit
下面,我們來分析下這個批處理
bcp "SELECT * FROM sportSys.dbo.competitions wheresportSys.dbo.competitions.userId="+%1 queryout %2competitions.xls -T -c>>%3log.txt
bcp 這個是語法
雙引號里面寫的是Sql語句
%1、%2、%3是要傳遞給bat文件的參數
%1表示第一個參數,%2表示第二個參數,%3表示第三個參數。
本人的這三個參數的意思分別是:
第一個參數:查詢條件
第二個參數:導出文件保存的位置
第三個參數:輸出日志保存的位置
②Java程序中調用
導出文件publicString backUp()throwsException {
try{
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
Map session = ActionContext.getContext().getSession();
String userId = session.get("userId").toString();
String homeDir1 = request.getSession().getServletContext()
.getRealPath("/");
//Runtime.getRuntime().exec("notepad");
Runtime.getRuntime().exec(
"cmd /k start /b "+homeDir1+"backUp\\backupBy.bat"+" "+ userId +" "+
homeDir1+"download"+File.separatorChar + userId+File.separatorChar+" "+
homeDir1+"download"+File.separatorChar + userId+File.separatorChar);
}catch(IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
returnINPUT;
}
returnSUCCESS;
}
Java中調用命令行程序,的方式就是第11行Runtime.getRuntime().exec(
"cmd /k start /b "+homeDir1+"backUp\\backupBy.bat"+" "+ userId +" "+
homeDir1+"download"+File.separatorChar + userId+File.separatorChar+" "+
homeDir1+"download"+File.separatorChar + userId+File.separatorChar);
Runtime:
每個 Java 應用程序都有一個Runtime類實例,使應用程序能夠與其運行的環境相連接。可以通過getRuntime方法獲取當前運行時。
應用程序不能創建自己的 Runtime 類實例。public Process exec(String command)
throws IOException在單獨的進程中執行指定的字符串命令。
這是一個很有用的方法。對于 exec(command) 形式的調用而言,其行為與調用 exec(command, null, null) 完全相同。
參數:
command - 一條指定的系統命令。
返回:
一個新的 Process 對象,用于管理子進程
拋出:
SecurityException - 如果安全管理器存在,并且其 checkExec 方法不允許創建子進程
IOException - 如果發生 I/O 錯誤
NullPointerException - 如果 command 為 null
IllegalArgumentException - 如果 command 為空
另請參見:
exec(String[], String[], File), ProcessBuilder
為了使調用bat文件來運行的時候,不至于彈出一個黑框,
加入/b參數 即可解決!
③導入
bcp sportSys.dbo.competitions in %1competitions.xls -c -t
以上便是導入的指令! 同樣也可以設置將待導入的文件全部放在目錄中,然后導入即可!
④壓縮成Zip文件-工具類(網上有寫好的ZipUtil)
packagecom.yaxing.util;
importjava.io.BufferedInputStream;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.util.jar.JarEntry;
importjava.util.jar.JarOutputStream;
importjava.util.jar.Manifest;
publicclassZipUtil {
protectedstaticbyte[] buf =newbyte[1024];
/**
* 私有構造函數防止被構建
*/
privateZipUtil() {
}
/**
* 遍歷目錄并添加文件.
*
* @param jos
* ? ? ? ? ? ?- JAR 輸出流
* @param file
* ? ? ? ? ? ?- 目錄文件名
* @param pathName
* ? ? ? ? ? ?- ZIP中的目錄名
* @throws IOException
* @throws FileNotFoundException
*/
privatestaticvoidrecurseFiles(finalJarOutputStream jos,
finalFile file,finalString pathName)throwsIOException,
FileNotFoundException {
// 文件夾則往下遍歷
if(file.isDirectory()) {
finalString sPathName = pathName + file.getName() +"/";
jos.putNextEntry(newJarEntry(sPathName));
finalString[] fileNames = file.list();
if(fileNames !=null) {
for(inti =0; i < fileNames.length; i++) {
recurseFiles(jos,newFile(file, fileNames[i]), sPathName);
}
}
}
// 讀取文件到ZIP/JAR文件條目
else{
// 使用指定名稱創建新的 ZIP/JAR 條目
finalJarEntry jarEntry =newJarEntry(pathName + file.getName());
finalFileInputStream fin =newFileInputStream(file);
finalBufferedInputStream in =newBufferedInputStream(fin);
// 開始寫入新的 ZIP 文件條目并將流定位到條目數據的開始處。
jos.putNextEntry(jarEntry);
intlen;
while((len = in.read(buf)) >=0) {
// 將字節數組寫入當前 ZIP 條目數據
jos.write(buf,0, len);
}
in.close();
// 關閉當前 ZIP 條目并定位流以寫入下一個條目
jos.closeEntry();
}
}
/**
* 創建 ZIP/JAR 文件.
*
* @param directory
* ? ? ? ? ? ?- 要添加的目錄
* @param zipFile
* ? ? ? ? ? ?- 保存的 ZIP 文件名
* @param zipFolderName
* ? ? ? ? ? ?- ZIP 中的路徑名
* @param level
* ? ? ? ? ? ?- 壓縮級別(0~9)
* @throws IOException
* @throws FileNotFoundException
*/
publicstaticvoidmakeDirectoryToZip(finalFile directory,
finalFile zipFile,finalString zipFolderName,finalintlevel)
throwsIOException, FileNotFoundException {
FileOutputStream fos =null;
try{
// 輸出文件流
fos =newFileOutputStream(zipFile);
}catch(finalException e) {
// 建立打包后的空文件
newFile(zipFile.getParent()).mkdirs();
zipFile.createNewFile();
fos =newFileOutputStream(zipFile);
}
// 使用指定的 Manifest 創建新的 JarOutputStream。清單作為輸出流的第一個條目被寫入
finalJarOutputStream jos =newJarOutputStream(fos,newManifest());
jos.setLevel(checkZipLevel(level));
finalString[] fileNames = directory.list();
if(fileNames !=null) {
for(inti =0; i < fileNames.length; i++) {
// 對一級目錄下的所有文件或文件夾進行處理
recurseFiles(jos,newFile(directory, fileNames[i]),
zipFolderName ==null?"": zipFolderName);
}
}
// 關閉 ZIP 輸出流和正在過濾的流。
jos.close();
}
/**
* 檢查并設置有效的壓縮級別,避免壓縮級別設置錯的異常
*
* @param level
* ? ? ? ? ? ?- 壓縮級別
* @return 有效的壓縮級別或者默認壓縮級別
*/
publicstaticintcheckZipLevel(finalintlevel) {
if(level <0|| level >9) {
return7;
}else{
returnlevel;
}
}
publicstaticvoidmain(finalString args[])throwsFileNotFoundException,
IOException {
// makeDirectoryToZip();
finalString homeDir = System.getProperty("user.dir");
System.out.println(homeDir);
finalFile zipFile =newFile(homeDir,"download"+ File.separatorChar
+"test.zip");
finalFile pagesDirectory =newFile(homeDir,"src");
System.out.println("Making zip file from folder /src to "+ zipFile);
ZipUtil.makeDirectoryToZip(pagesDirectory, zipFile,"",9);
System.out.println("Zip file "+ zipFile +" has been made.");
}
}
⑤Struts2執行Action里面的方法
publicString execute()throwsException {
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
Map session = ActionContext.getContext().getSession();
String userId = session.get("userId").toString();
finalString homeDir = request.getSession().getServletContext()
.getRealPath("/");// 打包后文件的位置及名稱
finalFile zipFile =newFile(homeDir,"download"+ File.separatorChar
+ userId + File.separatorChar + userId +"bak.zip");// 要打包的文件夾路徑
// if((new File(userId).isDirectory())){
// System.out.println("文件夾"+userId+"已存在!創建失敗!");
// }else{
// new File(userId).mkdir();
// System.out.println("創建文件夾"+userId+"成功!");
// }
finalFile pagesDirectory =newFile(homeDir,"download/"+ userId);
LOG.info("Making zip file from folder /"+ userId +" to "+ zipFile);// 壓縮文件
ZipUtil.makeDirectoryToZip(pagesDirectory, zipFile,"",9);
LOG.info("Zip file "+ zipFile +" has been made.");
response.sendRedirect("../download/"+ userId +"/"+ userId
+"bak.zip");
returnnull;
// return super.execute();
}
壓縮文件創建之后,返回該壓縮包,提供用戶下載!用戶將下載的文件導入客戶端系統中,即可,
四、總結
本文總結了Java中調用批處理文件,給批處理文件傳遞參數的使用方法。依據此,可以實現項目中多種用途的數據備份。
歡迎各位交流,如有更好的方法,歡迎指出,謝謝!
總結
以上是生活随笔為你收集整理的java批量处理数据库语句_Java项目中调用bat批处理进行多用户数据库备份的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何申请博客 下面是申请博客的步骤
- 下一篇: java中读取单个字符_如何使用Java