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

一、通过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




  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值