您的位置:首页 > 数据库 > Oracle

通过Java备份Oracle数据库和还原Oracle的方法

2015-11-27 17:56 661 查看

一、通过Java备份数据库

1、定义DBContext接口

public interface DBContext {

/**
* 解析JdbcUrl
*
* @param url
* @param info
*/
public void parseJdbcUrl(String url, DataSourceInfo info);

/**
* 备份数据库
*
* @param userName
*            数据库用户名
* @param password
*            数据密码
* @param dbName
*            数据库实例名
* @param host
*            连接数据库的ip
* @param dumpFile
*            备份文件名(全路径)
* @param tableNameList
*            待备份的数据库表名
* @return void
* @throws Exception
*/
public void backupDB(String userName, String password, String dbName,
String host, String dumpFile, List<String> tableNameList)
throws Exception;

/**
* 还原数据库
*
* @param userName
*            数据库用户名
* @param password
*            数据密码
* @param dbName
*            数据库实例名
* @param host
*            连接数据库的ip
* @param backupFile
*            已备份的数据库文件(全路径)
* @param ignoreTables
*            待备份的数据库表名
* @return void
* @throws Exception
*/
public void restoreDB(String userName, String password, String dbName,
String host, String backupFile) throws Exception;
}


2、DBContext实现类

public class OracleDBContext implements DBContext {

// 日志
Logger log = Logger.getLogger(OracleDBContext.class);

/**
* 解析oracle连接jdbc的url
*
* @return void
*/
public void parseJdbcUrl(String url, DataSourceInfo info) {
int end = url.indexOf("?");
end = (end == -1) ? url.length() : end;
url = url.substring(0, end);
int start = url.lastIndexOf(":");
String dbName = url.substring(start + 1);

url = url.substring(0, start);
url = url.substring(url.lastIndexOf("@") + 1);
String[] s = url.split(":");
info.setDbName(dbName);
info.setHost(s[0]);
info.setPort(Integer.parseInt(s[1]));
}

public void backupDB(String userName, String password, String dbName,
String host, String dumpFile, List<String> tableNameList)
throws Exception {
StringBuffer stringBuffer = new StringBuffer();

// 用户名
stringBuffer.append("exp ");
stringBuffer.append(userName);
stringBuffer.append("/");

// 密码
stringBuffer.append(password);
stringBuffer.append("@");

// 连接数据库的ip
stringBuffer.append(host);
stringBuffer.append("/");

// 数据库名称
stringBuffer.append(dbName);

stringBuffer.append(" file=");
stringBuffer.append(dumpFile);

// 导出权限
stringBuffer.append(" grants=y");

// 按照用户全部导出
stringBuffer.append(" owner=");
stringBuffer.append(userName);

// 按照指定表名导出
/*stringBuffer.append(" tables=(");
for (int i = 0; i < tableNameList.size(); i++) {
stringBuffer.append(tableNameList.get(i));
if (i < tableNameList.size() - 1) {
stringBuffer.append(",");
}
}
stringBuffer.append(")");*/

String cmdStr = stringBuffer.toString();

// 得到jvm的运行环境
Runtime rt = Runtime.getRuntime();
// 在单独的进程中执行指定的字符串命令。
Process process = rt.exec(cmdStr);

// 处理进程挂起
String line = null;
BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()));
//读取ErrorStream很关键,这个解决了挂起的问题。
while ((line = br.readLine()) != null){
log.info(line);
}

// 导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。
process.waitFor();

}

public void restoreDB(String userName, String password, String dbName,
String host, String backupFile) throws Exception {
StringBuffer stringBuffer = new StringBuffer();

// 用户名
stringBuffer.append("imp ");
stringBuffer.append(userName);
stringBuffer.append("/");

// 密码
stringBuffer.append(password);
stringBuffer.append("@");

// 连接数据库的ip
stringBuffer.append(host);
stringBuffer.append("/");

// 数据库名称
stringBuffer.append(dbName);
// 备份文件路径
stringBuffer.append(" file=");
stringBuffer.append(backupFile);
stringBuffer.append(" ignore=y full=y grants=y");

String cmdStr = stringBuffer.toString();

// 得到jvm的运行环境
Runtime rt = Runtime.getRuntime();
// 在单独的进程中执行指定的字符串命令。
Process process = rt.exec(cmdStr);

// 处理进程挂起
String line = null;
BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()));
//读取ErrorStream很关键,这个解决了挂起的问题。
while ((line = br.readLine()) != null){
log.info(line);
}
// 导致当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。
process.waitFor();
}

}


3、用于解析数据库配置信息的工具类

public class DBTool {

// 私有的构造方法
private DBTool() {

}

/**
* 得到数据库类型
*
* @return String
*/
public static String getDataBaseType() {
String dataBaseType = null;

// 获取当前色sessionFactory
LocalSessionFactoryBean sessionFactory = getLocalSessionFactoryBean();
if (null != sessionFactory) {

// 通过sessionFactory获取数据源
DataSource dataSource = sessionFactory.getDataSource();

// spring里的c3p0数据源
if (dataSource instanceof ComboPooledDataSource) {
ComboPooledDataSource comboPooledDataSource = (ComboPooledDataSource) dataSource;

// 数据库驱动信息
String driveClass = comboPooledDataSource.getDriverClass();

// 根据数据库驱动信息判断连接的数据库类型
if (null != driveClass) {
if (driveClass.indexOf("postgresql") > -1) {
dataBaseType = "postgresql";
} else if (driveClass.indexOf("OracleDriver") > -1) {
dataBaseType = "oracle";
}
}
}
}

return dataBaseType;
}

/**
* 是否是postgreSQL
*
* @return boolean
*/
public static boolean isPostgreSQL() {
return "postgresql".equals(getDataBaseType());
}

/**
* 是否是oracle
*
* @return boolean
*/
public static boolean isOracle() {
return "oracle".equals(getDataBaseType());
}

/**
* 得到数据库上下文
*
* @author chenweiyf2
* @return DBContext
*/
public static DBContext getDBContext() {
if (isPostgreSQL()) {
return new PostgreSQLDBContext();
} else {
return new OracleDBContext();
}
}

/**
* 获取连接数据库信息
*
* @return DataSourceInfo
*/
public static DataSourceInfo getDataSourceInfo() {
DataSourceInfo dataSourceInfo = new DataSourceInfo();

// 当前sessionFactory
LocalSessionFactoryBean sessionFactory = getLocalSessionFactoryBean();
if (null != sessionFactory) {

// 数据源信息
DataSource dataSource = sessionFactory.getDataSource();
String driver = null;
String url = null;
String userName = null;
String password = null;
String encoding = null;

// c3p0数据源
if (dataSource instanceof BasicDataSource) {
BasicDataSource basicDataSource = (BasicDataSource) dataSource;

driver = basicDataSource.getDriverClassName();
url = basicDataSource.getUrl();
userName = basicDataSource.getUsername();
password = basicDataSource.getPassword();
}
dataSourceInfo.setDriver(driver);
dataSourceInfo.setUserName(userName);
dataSourceInfo.setPassword(password);
dataSourceInfo.setUrl(url);

// 通过url获取数据库的实例名、连接数据库ip、端口
if (null != url) {
getDBContext().parseJdbcUrl(url, dataSourceInfo);
Pattern pattern = Pattern.compile("UTF-8|GBK|GB2312",
Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(url);

// 看连接信息中是否有设置编码
if (matcher.find()) {
encoding = matcher.group();
}
}
dataSourceInfo.setEncoding(encoding);
}

return dataSourceInfo;
}

/**
* 得到当前使用的SessionFactory
*
* @return LocalSessionFactoryBean
*/
@SuppressWarnings("rawtypes")
public static LocalSessionFactoryBean getLocalSessionFactoryBean() {
LocalSessionFactoryBean sessionFactory = null;

// 获取由spring管理的所有的bean,获取到的是一个map集
Map map = AppContext.getContext().getBeansOfType(
LocalSessionFactoryBean.class);

// 寻找LocalSessionFactoryBean
for (Object obj : map.values()) {
if (obj instanceof LocalSessionFactoryBean) {
sessionFactory = (LocalSessionFactoryBean) obj;
break;
}
}

return sessionFactory;
}

/**
* 数据备份
*
* @param filePath
*            备份文件名(全路径)
* @param valueList
*            数据库表名list
* @return String 返回信息
* @throws Exception
*/
public static String backupDB(String filePath, List<String> valueList)
throws Exception {
String responseStr = "-1";

DataSourceInfo dataSourceInfo = getDataSourceInfo();

// 根据上下文进行数据备份
// (待优化:备份数据库的大小,备份的操作系统,备份路径磁盘、文件夹的大小,备份结果文件的格式)
getDBContext().backupDB(dataSourceInfo.getUserName(),
dataSourceInfo.getPassword(), dataSourceInfo.getDbName(),
dataSourceInfo.getHost(), filePath, valueList);

// 备份最终结果是产生备份的文件,通过此判断是否已备份成功
File file = new File(filePath);
if (file.exists()) {
responseStr = filePath;
} else {
Log.error("数据备份失败!");
}

return responseStr;
}

/**
* 数据还原
*
* @param resotreFilePath
*            文件名(全路径)
* @return void
* @throws Exception
*/
public static void restoreDB(String resotreFilePath) throws Exception {
DataSourceInfo dataSourceInfo = getDataSourceInfo();

// 数据还原过程,调用cmd命令,但无法得知调用后的结果如何,所以无法通过返回值来判断是否还原成功
// (待优化:如何判断是否还原成功,还原文件的大小)
getDBContext().restoreDB(dataSourceInfo.getUserName(),
dataSourceInfo.getPassword(), dataSourceInfo.getDbName(),
dataSourceInfo.getHost(), resotreFilePath);
}
}


二、数据库还原操作

由于Oracle 数据库还原数据库时必须断开现有链接,所以无法实现在线还原功能,需要通过还原脚本完成。

1、还原前需要删除数据库原有资源

--.sql脚本
--唯一注意的是下面的f:\dropobj.sql 为操作的.sql;
--你的电脑没有F盘,请换为D或者E其他存在的盘符
--用于删除当前用户的所有对象
--use for drop all objects in current user;
set heading off;
set feedback off;
spool %logdir%\dropobj.sql;

prompt --删除约束条件
select 'alter table '||table_name||' drop constraint '||constraint_name||' ;' from user_constraints where constraint_type='R';

prompt --删除表空间
select 'drop table '||table_name ||';' from user_tables;

prompt --删除视图
select 'drop view ' ||view_name||';' from user_views;

prompt --删除数字序列
select 'drop sequence ' ||sequence_name||';' from user_sequences;

--prompt --删除函数
--select 'drop function ' ||object_name||';'  from user_objects
--where object_type='FUNCTION';

prompt --删除存储过程
select 'drop procedure '||object_name||';' from user_objects
where object_type='PROCEDURE';

prompt --删除包
prompt --删除包内容
select 'drop package '|| object_name||';' from user_objects
where object_type='PACKAGE';

prompt --删除数据库链接
select 'drop database link '|| object_name||';' from user_objects
where object_type='DATABASE LINK';

spool off
set heading on;
set feedback on;

spool %logdir%\dropobj.log
@@%logdir%\dropobj.sql;
host del %logdir%\dropobj.sql;
--done for drop objects in current user;
--在SQL*PLUS 将这整段作为.sql导入或者直接复制黏贴,按F5执行,完成。
commit;
exit;


2、还原脚本

@echo 数据还原程序会先删除数据库文件再进行还原,确认操作请按任意键继续......
@echo off
pause>nul
set /p ip=请输入数据库IP:
@echo off
set /p file=请输入还原文件的完整路径:
@echo 系统开始执行还原程序,请不要关闭本界面.....
@echo off
set logdir=log%date:~0,4%%date:~5,2%%date:~8,2%
if not exist %logdir% mkdir %logdir%
@echo on
@echo 建立日志文件夹完成......
@echo off

sqlplus UserName/password@%ip%/orcl @deleteObject.sql

@echo on
@echo 删除数据库文件完成,执行还原语句请按任意键......
@echo off
pause;

imp IVMS8630/Hik123_CityParking@%ip%/orcl fromuser=ivms8630 touser=ivms8630 grants=y ignore=y file=%file%

@echo on
@echo 还原完成......
@echo off
@echo 数据还原程序已完成还原操作,请按按任意键退出......
@echo off
pause>nul
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: