通过jdbc实现Oracle备份到Mysql

来源:互联网 发布:合同软件 编辑:程序博客网 时间:2024/06/05 16:42

一直用的系统是 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