通过jdbc实现Oracle备份到Mysql
程序员文章站
2022-03-17 12:38:26
...
一直用的系统是 Oracle的数据库,现在一个客户比较小,不想投入钱购买数据库软件,所以只能使用Mysql,需要将框架中的一些表结构、记录从Oracle导入到Mysql中去。网上没找到好用的软件,所以决定自己弄一个小程序实现异构库备份:
思路比较简单, 先生成建表语句并在mysql库中执行,在生成insert语句在mysql中执行。
一: 生成建表语句重点是需要获取表的字段,默认值,是否为空, 字段类型、字段长度等, 万幸的是这些jdbc都有实现,通过Connect获取数据库的DatabaseMetaData--dmd,
System.out.println("加载Oracle链接0..."); connect = connect(0); System.out.println("加载Mysql链接1..."); insertConnect = connect(1); System.out.println("获取dmd..."); dmd = connect.getMetaData();
再通过DatabaseMetaData--dmd查询表单字段信息,
ResultSet colrs = dmd.getColumns("%", dmd.getUserName(),table.toUpperCase(), "%");
然后解析获取到的ResultSet信息后即可获取到字段的全部信息,生成建表语句:
二:取生成insert语句类似,需要适用select语句查询表的信息,然后循环解析每一行的记录,生成insert插入,此处执行sql的是PreparedStatement,可以循环适用insert语句,仅需要改变每一次动态设置的值属性即可。
全部代码比较简单,直接上代码:
有两个类:jdbc工具类:JDBCUtil.java
import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class JDBCUtil { public static Connection connect(int type) { Connection conn; if (type == 0) {//oracle conn = connectOracle(); } else { //Mysql conn = connectMysql(); } return conn; } /** * 连接Oracle * * @return */ public static Connection connectMysql() { // 连接MySql数据库,用户名和密码 String username = "111212"; String password = "2121"; String url = "jdbc:mysql://192.168.1.1/training?user=" + username+ "&password=" + password + ""; Connection conn = null; try { // 加载MySql的驱动类 Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection(url); } catch (ClassNotFoundException e) { System.out.println("找不到驱动程序类 ,加载驱动失败!"); e.printStackTrace(); } catch (SQLException se) { System.out.println("数据库连接失败!"); se.printStackTrace(); } return conn; } /** * 连接Oracle * * @return */ public static Connection connectOracle() { String url = "jdbc:oracle:thin:@192.168.1.1:1521:orcl"; // 连接MySql数据库,用户名和密码都是root String username = "abcaf"; String password = "syjgagagac"; Connection conn = null; try { // 加载MySql的驱动类 Class.forName("oracle.jdbc.OracleDriver"); conn = DriverManager.getConnection(url, username, password); } catch (ClassNotFoundException e) { System.out.println("找不到驱动程序类 ,加载驱动失败!"); e.printStackTrace(); } catch (SQLException se) { System.out.println("数据库连接失败!"); se.printStackTrace(); } return conn; } public static List getColumnNames(ResultSetMetaData meta) throws SQLException{ List list = new ArrayList(); for (int i = 1; i <= meta.getColumnCount(); i++) { list.add(meta.getColumnName(i)); } return list; } // ResultSetMetaData 使用示例 // 此方法参考 http://blog.csdn.net/yirentianran/article/details/2950321 public static void demoResultSetMetaData(ResultSetMetaData data) throws SQLException { for (int i = 1; i <= data.getColumnCount(); i++) { // 获得所有列的数目及实际列数 int columnCount = data.getColumnCount(); // 获得指定列的列名 String columnName = data.getColumnName(i); // 获得指定列的列值 // String columnValue = rs.getString(i); // 获得指定列的数据类型 int columnType = data.getColumnType(i); // 获得指定列的数据类型名 String columnTypeName = data.getColumnTypeName(i); // 所在的Catalog名字 String catalogName = data.getCatalogName(i); // 对应数据类型的类 String columnClassName = data.getColumnClassName(i); // 在数据库中类型的最大字符个数 int columnDisplaySize = data.getColumnDisplaySize(i); // 默认的列的标题 String columnLabel = data.getColumnLabel(i); // 获得列的模式 String schemaName = data.getSchemaName(i); // 某列类型的精确度(类型的长度) int precision = data.getPrecision(i); // 小数点后的位数 int scale = data.getScale(i); // 获取某列对应的表名 String tableName = data.getTableName(i); // 是否自动递增 boolean isAutoInctement = data.isAutoIncrement(i); // 在数据库中是否为货币型 boolean isCurrency = data.isCurrency(i); // 是否为空 int isNullable = data.isNullable(i); // 是否为只读 boolean isReadOnly = data.isReadOnly(i); // 能否出现在where中 boolean isSearchable = data.isSearchable(i); System.out.println(columnCount); System.out.println("获得列" + i + "的字段名称:" + columnName); // System.out.println("获得列" + i + "的字段值:" + columnValue); System.out.println("获得列" + i + "的类型,返回SqlType中的编号:" + columnType); System.out.println("获得列" + i + "的数据类型名:" + columnTypeName); System.out.println("获得列" + i + "所在的Catalog名字:" + catalogName); System.out.println("获得列" + i + "对应数据类型的类:" + columnClassName); System.out.println("获得列" + i + "在数据库中类型的最大字符个数:" + columnDisplaySize); System.out.println("获得列" + i + "的默认的列的标题:" + columnLabel); System.out.println("获得列" + i + "的模式:" + schemaName); System.out.println("获得列" + i + "类型的精确度(类型的长度):" + precision); System.out.println("获得列" + i + "小数点后的位数:" + scale); System.out.println("获得列" + i + "对应的表名:" + tableName); System.out.println("获得列" + i + "是否自动递增:" + isAutoInctement); System.out.println("获得列" + i + "在数据库中是否为货币型:" + isCurrency); System.out.println("获得列" + i + "是否为空:" + isNullable); System.out.println("获得列" + i + "是否为只读:" + isReadOnly); System.out.println("获得列" + i + "能否出现在where中:" + isSearchable); } } // 演示 DatabaseMetaData public static void demoDatabaseMetaData() { try { Connection con = connect(0); // DatabaseMetaData dmd = con.getMetaData(); System.out.println("当前数据库是:" + dmd.getDatabaseProductName()); System.out.println("当前数据库版本:" + dmd.getDatabaseProductVersion()); System.out.println("当前数据库驱动:" + dmd.getDriverVersion()); System.out.println("当前数据库URL:" + dmd.getURL()); System.out.println("当前数据库是否是只读模式?:" + dmd.isReadOnly()); System.out.println("当前数据库是否支持批量更新?:" + dmd.supportsBatchUpdates()); System.out .println("当前数据库是否支持结果集的双向移动(数据库数据变动不在ResultSet体现)?:" + dmd.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE)); System.out .println("当前数据库是否支持结果集的双向移动(数据库数据变动会影响到ResultSet的内容)?:" + dmd.supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE)); System.out.println("========================================"); // ResultSet rs = dmd.getTables(null, null, "%", null); // System.out.println("表名" + "," + "表类型"); /* * while (rs.next()) { String tname = * rs.getString("TABLE_NAME").toLowerCase(); * if(!tname.startsWith("t_")){ continue; } * System.out.println(rs.getString("TABLE_NAME") + ","+ * rs.getString("TABLE_TYPE")); } */ System.out.println("========================================"); ResultSet rs = dmd.getPrimaryKeys(null, "SYJC", "t_mz_djlr".toUpperCase()); while (rs.next()) { System.out .println(rs.getString(3) + "表的主键是:" + rs.getString(4)); } System.out.println("========================================"); rs = dmd.getColumns("%", "SYJC", "t_mz_djlr", "%"); System.out.println("t_student表包含的字段:"); while (rs.next()) { System.out.println(rs.getString(4) + " " + rs.getString(6) + "(" + rs.getString(7) + ");"); } System.out.println("========================================"); } catch (Exception e) { System.out.println("数据库操作出现异常"); } } }
还有一个实现 解析字段信息生成建表语句、解析结果生成insert语句的类DBBackUtil.java
import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class DBBackUtil extends JDBCUtil{ public static Connection connect; public static Connection insertConnect; public static DatabaseMetaData dmd; public static Map dataTypesMap = new HashMap(); public static List<String> types = new ArrayList(); public static Map<String,Boolean> unneedLength = new HashMap(); static{ /** * 此处对象的是 jdbcType 将要转换到mysql的数据类型 */ dataTypesMap.put(12+"","VARCHAR"); dataTypesMap.put(3+"","DECIMAL"); dataTypesMap.put(93+"","TIMESTAMP"); dataTypesMap.put(1+"","CHAR"); dataTypesMap.put(6+"","DECIMAL"); dataTypesMap.put(2005+"","LONGTEXT"); dataTypesMap.put(1111+"","VARCHAR"); /***不需要长度的字段, clob(longtext)、TIMESTAMP*/ unneedLength.put(93+"",true); unneedLength.put(2005+"",true); types.add("VARCHAR2"); types.add("NUMBER"); types.add("DATE"); types.add("CHAR"); types.add("FLOAT"); types.add("CLOB"); types.add("NCHAR"); } public static void main(String[] args) throws SQLException { System.out.println("加载Oracle链接0..."); connect = connect(0); System.out.println("加载Mysql链接1..."); insertConnect = connect(1); System.out.println("获取dmd..."); dmd = connect.getMetaData(); String[] tables = { "t_base_zg" }; String table = null; for (int j = 0; j < tables.length; j++) { table = tables[j]; System.out.println("==========================================================="); createCreateSQL(table); System.out.println("==========================================================="); System.out.println("插入开始表:"+table); createInsertSQL(table); System.out.println("插入表结束:"+table); System.out.println("==========================================================="); } // System.out.println("*******************************************"); // for (String ty : types) { // System.out.println(ty); // } // System.out.println("*******************************************"); connect.close(); } private static void createInsertSQL(String table) throws SQLException { Statement stmt = createStmt(connect); String sql = "select * from "+table; System.out.println("查询表数据 "+table); ResultSet rs = stmt.executeQuery(sql); System.out.println("获取表字段。。。。"+table); List<String> columns = getColumnNames(rs.getMetaData()); StringBuffer insertSql = new StringBuffer("INSERT INTO "+table+"("); for (String col : columns) { insertSql.append(col+","); } insertSql.delete(insertSql.length()-1, insertSql.length()); insertSql.append(") \n values("); for (String col : columns) { insertSql.append("?,"); } insertSql.delete(insertSql.length()-1, insertSql.length()); insertSql.append(")"); System.out.println(insertSql.toString()); System.out.println("循环插入数据......"); PreparedStatement preStmt = null; while(rs.next()){ preStmt = createPreStmt(insertConnect, insertSql.toString()); //循环结果集 执行插入操作 for (int i = 0; i < columns.size(); i++) { Object obj = rs.getObject(columns.get(i)); //System.out.println(obj+"\t"+(obj!=null?obj.getClass():"")); preStmt.setObject(i+1, obj); } int count = preStmt.executeUpdate(); System.out.println("插入 "+count+"条"); preStmt.clearBatch(); preStmt.clearParameters(); preStmt.close(); } rs.close(); } /** * 生成建表语句 * @param table * @return * @throws SQLException */ public static String createCreateSQL(String table) throws SQLException{ ResultSet colrs = dmd.getColumns("%", dmd.getUserName(),table.toUpperCase(), "%"); StringBuffer sb = new StringBuffer("create table " + table + "(\n"); System.out.println("获取表 【"+table+"】的字段创建按create语句"); while (colrs.next()) { String columnName = colrs.getString("COLUMN_NAME"); //字段名 int dataType = colrs.getInt("DATA_TYPE"); //数据类型 数字表示 String dataTypeName = (String) dataTypesMap.get(dataType+""); String typeName = colrs.getString("TYPE_NAME"); //类型名 varchar2等,数据库的实际字段类型 if(!types.contains(typeName)){ types.add(typeName); } int columnSize = colrs.getInt("COLUMN_SIZE"); String remarks = colrs.getString("REMARKS"); int nullable = colrs.getInt("NULLABLE"); String columnDef = colrs.getString("COLUMN_DEF"); sb.append("\t"+columnName.toLowerCase()+"\t");//字段名 if( columnSize == 4000 && "VARCHAR".equals(dataTypeName)){ sb.append("Text");//daatype }else{ sb.append(dataTypeName);//daatype } Boolean unNeedLength = unneedLength.get(dataType+""); if(!(unNeedLength!=null && unNeedLength.booleanValue())){ if("DECIMAL".equals(dataTypeName)){ sb.append("("+(columnSize>10?10:columnSize)); //字段长度 }else{ sb.append("("+columnSize); //字段长度 } sb.append(")"); } sb.append("\t"); //sb.append("typeName:"+typeName+"\t"); //sb.append("dataType:"+dataType+"\t"); if(columnDef!=null && !"".equals(columnDef.trim())){ sb.append("default "+columnDef+" \t"); //默认值 } //sb.append("remarks:"+remarks+"\t"); sb.append((nullable == 0 ? " not null " : "")+","); //是否为空 sb.append("\n"); } //去掉最后的逗号 sb.replace(sb.length()-3, sb.length(), ""); System.out.println("获取表 【"+table+"】的主键...."); /** * 生成主键 */ String keySql = createKeySqlByTableName(table); if(keySql!=null && keySql.length()>0){ sb.append(",\n"); sb.append("\t"+keySql+"\n"); } sb.append(") ENGINE=INNODB ;"); System.out.println(sb.toString()); Statement stmt = createStmt(insertConnect); System.out.println("执行表 【"+table+"】的建表语句 ...."); boolean runRs = stmt.execute(sb.toString()); System.out.println("上述建表语句 执行完成"); return sb.toString(); } /** * 获取表主键集合 * @return * @throws SQLException */ private static List getTableKeys(String tableName) throws SQLException{ ResultSet rs = dmd.getPrimaryKeys(null, "SYJC", tableName.toUpperCase());//此处旭要将表名设置成大写 oracle 只认大写 List list = new ArrayList(); while (rs.next()) { list.add(rs.getString(4).toLowerCase()); } rs.close(); return list; } /** * 将表名拼接成Key sql * @param tableName * @return * @throws SQLException */ public static String createKeySqlByTableName(String tableName) throws SQLException{ List list = getTableKeys(tableName); return createKeySql(list); } /** * 将字段拼接成Key sql * @param list * @return */ public static String createKeySql(List<String> list){ if(list==null || list.size()<=0){ return null; } StringBuffer keySql = new StringBuffer(); keySql.append("primary key ("); for (int i = 0; i < list.size(); i++) { if(i!=0 ){ keySql.append(","); } keySql.append(list.get(i)); } keySql.append(")"); return keySql.toString(); } public static PreparedStatement createPreStmt(Connection conn, String sql) { PreparedStatement pstmt = null; try { pstmt = conn.prepareStatement(sql); } catch (SQLException e) { System.out.println("生成预处理stmt失败"); e.printStackTrace(); } return pstmt; } public static Statement createStmt(Connection conn) { Statement pstmt = null; try { pstmt = conn.createStatement(); } catch (SQLException e) { System.out.println("生成预处理stmt失败"); e.printStackTrace(); } return pstmt; } /** * 解析ResultSet的单条记录,不进行 ResultSet 的next移动处理 * * @param rs * @return */ private static Map<String, Object> parseResultSetToMap(ResultSet rs) { // if (null == rs) { return null; } // Map<String, Object> map = new HashMap<String, Object>(); // try { ResultSetMetaData meta = rs.getMetaData(); // int colNum = meta.getColumnCount(); // for (int i = 1; i <= colNum; i++) { // 列名 String name = meta.getColumnLabel(i); // i+1 Object value = rs.getObject(i); // 加入属性 map.put(name, value); } } catch (SQLException e) { e.printStackTrace(); } // return map; } // /** // * varchar2 number date char clob nchar // * // * @return // */ // public static Map createMappingRelation() { // Map map = new HashMap(); // map.put("varchar2", "varchar"); // map.put("number", "varchar"); // map.put("date", "datetime"); // map.put("char", "charo"); // map.put("clob", "mediumtext"); // map.put("nchar", "varchar"); // return map; // } }
通过dmd 获取字段信息 请参考:http://blog.sina.com.cn/s/blog_707a9f0601014y1y.html
转载请注明出处:http://314649444.iteye.com/admin/blogs/2307007
推荐阅读
-
Python实现备份EC2的重要文件和MySQL数据库到S3
-
通过创建SQLServer 2005到 Oracle10g 的链接服务器实现异构数据库数据转换方案
-
通过Xtrabackup实现MySQL实例的全库备份与按需单库恢复
-
抽取oracle数据到mysql数据库的实现过程
-
Navicat Premium实现oracle到mysql的数据库迁移
-
maven项目通过java加载mqtt存储到mysql数据库,实现发布和接收
-
Python实现备份EC2的重要文件和MySQL数据库到S3
-
通过创建SQLServer 2005到 Oracle10g 的链接服务器实现异构数据库数据转换方案
-
通过JDBC连接MySQL 8.0(Eclipse实现)
-
从MYSQL到oracle的迁移以及备份_MySQL