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

来源:互联网 发布:网络直播紫菱真实姓名 编辑:程序博客网 时间:2024/05/16 12:09

一、通过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("@");// 连接数据库的ipstringBuffer.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("@");// 连接数据库的ipstringBuffer.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;// 获取当前色sessionFactoryLocalSessionFactoryBean 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();// 当前sessionFactoryLocalSessionFactoryBean 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);// 寻找LocalSessionFactoryBeanfor (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_objectswhere object_type='PROCEDURE'; prompt --删除包prompt --删除包内容select 'drop package '|| object_name||';' from user_objectswhere object_type='PACKAGE';prompt --删除数据库链接select 'drop database link '|| object_name||';' from user_objectswhere object_type='DATABASE LINK'; spool offset 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 offpause>nulset /p ip=请输入数据库IP:@echo offset /p file=请输入还原文件的完整路径:@echo 系统开始执行还原程序,请不要关闭本界面.....@echo offset logdir=log%date:~0,4%%date:~5,2%%date:~8,2%if not exist %logdir% mkdir %logdir%@echo on@echo 建立日志文件夹完成......@echo offsqlplus UserName/password@%ip%/orcl @deleteObject.sql@echo on@echo 删除数据库文件完成,执行还原语句请按任意键......@echo offpause;imp IVMS8630/Hik123_CityParking@%ip%/orcl fromuser=ivms8630 touser=ivms8630 grants=y ignore=y file=%file%@echo on@echo 还原完成......@echo off@echo 数据还原程序已完成还原操作,请按按任意键退出......@echo offpause>nul




0 0