这几天遇到个数据迁移大字段的问题一直没有时间解决,今天终于有时间解决这个问题。
场景
SQL Server数据库某张表的数据迁移到Oracle数据库,早期未考虑特殊字段类型的问题,但真正业务应用测试时发现了问题,对应Oracle中该字段内容为空(迁移时忽略了)。需要我们依据主键将SQL Server表中的内容更新到Oracle上来,直接利用JDBC就可以处理此问题。
JDBC处理的一些总结
Oracle JDBC驱动程序有兼容问题,有JDBC3\JDBC4之分
Oracle下对CLOB的操作是字符流的形式,在JDBC4之前插入带有CLOB的数据需要分两步
JDBC4之后Oracle11G对这块的处理改善了很多
SQL Server数据库JDBC
示例代码
JDBC4.0对CLOB的插入
/** * 测试插入 * <p>1、注意Oracle的JDBC驱动为ojdbc6.jar * @throws SQLException */ public void insertDateNew() throws SQLException { String sql = "INSERT INTO ".concat(tableName).concat(" (ID,CONTENT) VALUES(?,?)"); PreparedStatement pstmt = null; try { this.conn.setAutoCommit(false); pstmt = this.conn.prepareStatement(sql); for (int i = 1; i < 50; i++) { pstmt.setString(1, String.valueOf(i)); Clob clob = this.conn.createClob(); clob.setString(1, "HelloWorld " + i); pstmt.setClob(2, clob); pstmt.addBatch(); } pstmt.executeBatch(); this.conn.commit(); } catch (SQLException e) { this.conn.rollback(); e.printStackTrace(); } finally { this.conn.setAutoCommit(true); DBUtils.close(pstmt); } }
JDBC3.0的插入
/** * 测试插入CLOB */ public void insertData() throws SQLException { String sql = "INSERT INTO ".concat(tableName).concat(" (ID,CONTENT) VALUES(?,EMPTY_CLOB())"); PreparedStatement pstmt = null; try { this.conn.setAutoCommit(false); pstmt = this.conn.prepareStatement(sql); for (int i = 1; i < 50; i++) { pstmt.setString(1, String.valueOf(i)); pstmt.addBatch(); } pstmt.executeBatch(); this.updateInsertCLOB(); this.conn.commit(); } catch (SQLException e) { this.conn.rollback(); e.printStackTrace(); } finally { this.conn.setAutoCommit(true); DBUtils.close(pstmt); } } /** * 支持未实现JDBC4的情况 * @param pstmt {@link PreparedStatement} * @throws SQLException */ private void updateInsertCLOB() throws SQLException { String sql = "SELECT ID,CONTENT FROM ".concat(tableName); PreparedStatement pstmt = null; ResultSet resultSet = null; try { pstmt = this.conn.prepareStatement(sql); resultSet = pstmt.executeQuery(sql); while (resultSet.next()) { Clob clobInst = resultSet.getClob(2); Writer writerInst = clobInst.setCharacterStream(1); writerInst.write("HelloWorld " + resultSet.getString(1)); writerInst.close(); } } catch (IOException e) { throw new SQLException(e.getCause()); } finally { DBUtils.close(pstmt); } }
字节/字符流类型处理
/** * 测试查询 * <p> * 1、TEXT类型直接getString即可 * <p> * 2、主要是BINARY类型的处理 * @throws SQLException */ public void queryDate() throws SQLException { String qrySql = "SELECT * FROM BLOB_TABLE A WHERE A.ID=?"; PreparedStatement pstmt = null; try { pstmt = this.conn.prepareStatement(qrySql); pstmt.setString(1, "1"); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { InputStream ins = rs.getBinaryStream("PHOTO"); restoreInputStream(ins); ins.close(); } } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { DBUtils.close(pstmt); } } /** * 转储输入流 * @param ins {@link InputStream} * @throws IOException IOException */ private void restoreInputStream(InputStream ins) { BufferedOutputStream bosInst = null; byte[] buff = new byte[1024 * 1024]; try { bosInst = new BufferedOutputStream(new FileOutputStream("C:\\ttt.zip")); int flag = -1; while ((flag = ins.read(buff)) != -1) { bosInst.write(buff, 0, flag); } bosInst.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (bosInst != null) { try { bosInst.close(); } catch (IOException e) { e.printStackTrace(); } } } }