您的位置:首页 > 数据库 > Oracle

使用JDBC处理Oracle大数据

2017-09-04 09:46 288 查看


一、Oracle中大数据处理

  在Oracle中,LOB(Large Object,大型对象)类型的字段现在用得越来越多了。因为这种类型的字段,容量大(最多能容纳4GB的数据),且一个表中可以有多个这种类型的字段,很灵活,适用于数据 量非常大的业务领域(如图象、档案等)。

  LOB类型分为BLOB和CLOB两种:BLOB即二进制大型对象(Binary Large Object),适用于存贮非文本的字节流数据(如程序、图象、影音等)。而CLOB,即字符型大型对象(Character Large Object),则与字符集相关,适于存贮文本型的数据(如历史档案、大部头著作等)。


二、搭建测试环境


2.1、建立两个测试用的数据库表

  建表SQL语句为:

1 CREATE TABLE TEST_CLOB ( ID NUMBER(3), CLOBCOL CLOB)
2
3 CREATE TABLE TEST_BLOB ( ID NUMBER(3), BLOBCOL BLOB)



2.2、搭建测试项目架构

  


2.3、编写db.properties配置文件

1 oracleDb_Driver=oracle.jdbc.driver.OracleDriver
2 oracleDb_Url=jdbc:oracle:thin:@localhost:1521:GACL
3 oracleDb_UserName=GACL_XDP
4 oracleDb_Password=P



2.4、编写JdbcUtils工具类

package me.gacl.utils;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JdbcUtils {

private static String oracleDb_Driver = null;
private static String oracleDb_Url = null;
private static String oracleDb_UserName = null;
private static String oracleDb_Password = null;

static{
try{
//读取db.properties文件中的数据库连接信息
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties prop = new Properties();
prop.load(in);

//获取数据库连接驱动
oracleDb_Driver = prop.getProperty("oracleDb_Driver");
//获取数据库连接URL地址
oracleDb_Url = prop.getProperty("oracleDb_Url");
//获取数据库连接用户名
oracleDb_UserName = prop.getProperty("oracleDb_UserName");
//获取数据库连接密码
oracleDb_Password = prop.getProperty("oracleDb_Password");

//加载数据库驱动
Class.forName(oracleDb_Driver);

}catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}

/**
* @Method: getOracleConnection
* @Description: 获取Oracle数据库连接对象
* @Anthor:孤傲苍狼
*
* @return Connection数据库连接对象
* @throws SQLException
*/
public static Connection getOracleConnection() throws SQLException{
return DriverManager.getConnection(oracleDb_Url, oracleDb_UserName,oracleDb_Password);
}

/**
* @Method: release
* @Description: 释放资源,
*     要释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象
* @Anthor:孤傲苍狼
*
* @param conn
* @param st
* @param rs
*/
public static void release(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
//关闭存储查询结果的ResultSet对象
rs.close();
}catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if(st!=null){
try{
//关闭负责执行SQL命令的Statement对象
st.close();
}catch (Exception e) {
e.printStackTrace();
}
}

if(conn!=null){
try{
//关闭Connection数据库连接对象
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}



三、JDBC处理Oracle大数据


3.1、JDBC处理CLOB数据

package me.gacl.demo;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.junit.Test;
import me.gacl.utils.JdbcUtils;

/**
* @ClassName: JdbcOperaOracleClob
* @Description:Oracle中字符型大型对象(Character Large Object)数据处理
* @author: 孤傲苍狼
* @date: 2014-10-7 下午3:53:19
*
*/
public class JdbcOperaOracleClob {

/**
CREATE TABLE TEST_CLOB ( ID NUMBER(3), CLOBCOL CLOB)
*/
/**
* @Method: clobInsert
* @Description:往数据库中插入一个新的CLOB对象
* @Anthor:孤傲苍狼
*
* @throws Exception
*/
@Test
public void clobInsert() throws Exception {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
conn = JdbcUtils.getOracleConnection();
boolean defaultCommit = conn.getAutoCommit();
/*开启事务,设定不自动提交 */
conn.setAutoCommit(false);
try {
/* 插入一个空的CLOB对象 */
String sql = "INSERT INTO TEST_CLOB VALUES (?, EMPTY_CLOB())";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 1);
stmt.executeUpdate();
/* 查询此CLOB对象并锁定 */
sql = "SELECT CLOBCOL FROM TEST_CLOB WHERE ID=? FOR UPDATE";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 1);
rs = stmt.executeQuery();
if (rs.next()) {
/* 取出此CLOB对象 */
oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
/* 向CLOB对象中写入数据 */
BufferedWriter out = new BufferedWriter(clob.getCharacterOutputStream());
//这种方式获取的路径,其中的空格会被使用“%20”代替
String path = JdbcOperaClob.class.getClassLoader().getResource("data.txt").getPath();
//将“%20”替换回空格
path = path.replaceAll("%20", " ");
BufferedR
10ff8
eader in = new BufferedReader(new FileReader(path));
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
in.close();
out.close();
}
/* 正式提交 */
conn.commit();
System.out.println("插入成功");
} catch (Exception ex) {
/* 出错回滚 */
conn.rollback();
throw ex;
}finally{
/* 恢复原提交状态 */
conn.setAutoCommit(defaultCommit);
JdbcUtils.release(conn,stmt,rs);
}

}

/**
* @Method: clobRead
* @Description: CLOB对象读取
* @Anthor:孤傲苍狼
*
* @throws Exception
*/
@Test
public void clobRead() throws Exception {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
conn = JdbcUtils.getOracleConnection();
boolean defaultCommit = conn.getAutoCommit();
conn.setAutoCommit(false);
try {
/* 查询CLOB对象 */
String sql = "SELECT * FROM TEST_CLOB WHERE ID=?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 1);
rs = stmt.executeQuery();
if (rs.next()) {
/* 获取CLOB对象 */
oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
/* 以字符形式输出 */
BufferedReader in = new BufferedReader(clob.getCharacterStream());
BufferedWriter out = new BufferedWriter(new FileWriter("D:\\2.txt"));
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
out.close();
in.close();
}
} catch (Exception ex) {
conn.rollback();
throw ex;
}finally{
/* 恢复原提交状态 */
conn.setAutoCommit(defaultCommit);
JdbcUtils.release(conn,stmt,rs);
}
}

/**
* @Method: clobModify
* @Description:修改CLOB对象(是在原CLOB对象基础上进行覆盖式的修改)
* @Anthor:孤傲苍狼
*
* @throws Exception
*/
@Test
public void clobModify() throws Exception {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
conn = JdbcUtils.getOracleConnection();
boolean defaultCommit = conn.getAutoCommit();
// 开启事务
conn.setAutoCommit(false);
try {
/* 查询CLOB对象并锁定 */
String sql = "SELECT CLOBCOL FROM TEST_CLOB WHERE ID=? FOR UPDATE";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 1);
rs = stmt.executeQuery();
if (rs.next()) {
/* 获取此CLOB对象 */
oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
/* 进行覆盖式修改 */
BufferedWriter out = new BufferedWriter(clob.getCharacterOutputStream());
// 这种方式获取的路径,其中的空格会被使用“%20”代替
String path = JdbcOperaClob.class.getClassLoader().getResource("data2.txt").getPath();
// 将“%20”替换回空格
path = path.replaceAll("%20", " ");
BufferedReader in = new BufferedReader(new FileReader(path));
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
in.close();
out.close();
}
/*提交事务 */
conn.commit();
} catch (Exception ex) {
/*出错回滚事务 */
conn.rollback();
throw ex;
}finally{
/*恢复原提交状态 */
conn.setAutoCommit(defaultCommit);
JdbcUtils.release(conn,stmt,rs);
}
}

/**
* @Method: clobReplace
* @Description:替换CLOB对象(将原CLOB对象清除,换成一个全新的CLOB对象)
* @Anthor:孤傲苍狼
*
* @throws Exception
*/
@Test
public void clobReplace() throws Exception {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
conn = JdbcUtils.getOracleConnection();
boolean defaultCommit = conn.getAutoCommit();
// 开启事务
conn.setAutoCommit(false);
try {
/* 清空原CLOB对象 */
String sql = "UPDATE TEST_CLOB SET CLOBCOL=EMPTY_CLOB() WHERE ID=?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 1);
stmt.executeUpdate();

/* 查询CLOB对象并锁定 */
sql = "SELECT CLOBCOL FROM TEST_CLOB WHERE ID=? FOR UPDATE";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 1);
rs = stmt.executeQuery();
if (rs.next()) {
/* 获取此CLOB对象 */
oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
/* 更新数据 */
BufferedWriter out = new BufferedWriter(clob.getCharacterOutputStream());
// 这种方式获取的路径,其中的空格会被使用“%20”代替
String path = JdbcOperaClob.class.getClassLoader().getResource("db.properties").getPath();
// 将“%20”替换回空格
path = path.replaceAll("%20", " ");
BufferedReader in = new BufferedReader(new FileReader(path));
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
in.close();
out.close();
}
/* 正式提交 */
conn.commit();
} catch (Exception ex) {
/* 出错回滚 */
conn.rollback();
throw ex;
} finally {
/* 恢复原提交状态 */
conn.setAutoCommit(defaultCommit);
JdbcUtils.release(conn, stmt, rs);
}
}
}



3.2、JDBC处理BLOB数据

  Oracle定义了一个BLOB字段用于保存二进制数据,但这个字段并不能存放真正的二进制数据,只能向这个字段存一个指针,然后把数据放到指针所指向的Oracle的LOB段中, LOB段是在数据库内部表的一部分。因而在操作Oracle的Blob之前,必须获得指针(定位器)才能进行Blob数据的读取和写入。

  如何获得表中的Blob指针呢? 可以先使用insert语句向表中插入一个空的blob(调用oracle的函数empty_blob()),这将创建一个blob的指针,然后再把这个empty的blob的指针查询出来,这样就可得到BLOB对象,从而读写blob数据了。

  1、插入空blob:insert into testblob(id,image) values(?,empty_blob())

  2、获得blob的cursor:

    select image from testblob where id=? for update 注意: 必 须加for update锁定该行,直至该行被修改完毕,保证不产生并发冲突。

    Blob b = rs.getBlob("image");

    

  3、利用 io和获取到的cursor往数据库读写数据

  注意:以上操作需开启事务。

  BLOB对象的存取范例

package me.gacl.demo;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.junit.Test;
import me.gacl.utils.JdbcUtils;

/**
* @ClassName: JdbcOperaOracleBlob
* @Description:Oracle中大数据处理
* @author: 孤傲苍狼
* @date: 2014-10-7 下午3:53:19
*
*/
public class JdbcOperaOracleBlob {

/**
* @Method: blobInsert
* @Description: 向数据库中插入一个新的BLOB对象
* @Anthor:孤傲苍狼
*
* @throws Exception
*/
@Test
public void blobInsert() throws Exception {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
boolean defaultCommit = true;
try {
conn = JdbcUtils.getOracleConnection();
//得到数据库事务处理的默认提交方式
defaultCommit = conn.getAutoCommit();
//1、开启事务
conn.setAutoCommit(false);
//2、插入一个空的BLOB对象
String sql = "INSERT INTO TEST_BLOB VALUES (?, EMPTY_BLOB())";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 1);
stmt.executeUpdate();
//3、查询此BLOB对象并锁定。注意: 必 须加for update锁定该行,直至该行被修改完毕,保证不产生并发冲突
sql = "SELECT BLOBCOL FROM TEST_BLOB WHERE ID=? FOR UPDATE";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 1);
rs = stmt.executeQuery();
if (rs.next()) {
//4、取出此BLOB对象 ,并强制转换成Oracle的BLOB对象
oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("BLOBCOL");
//5、使用IO向BLOB对象中写入数据
BufferedOutputStream out = new BufferedOutputStream(blob.getBinaryOutputStream());
BufferedInputStream in = new BufferedInputStream(JdbcOperaOracleBlob.class.getClassLoader().getResourceAsStream("01.jpg"));
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
in.close();
out.close();
}
//6、提交事务
conn.commit();
} catch (Exception ex) {
//7、出错回滚事务
conn.rollback();
throw ex;
} finally {
//8、恢复数据库事务处理的默认提交方式
conn.setAutoCommit(defaultCommit);
//释放资源
JdbcUtils.release(conn, stmt, rs);
}

}

/**
* @Method: blobModify
* @Description:修改BLOB对象(是在原BLOB对象基础上进行覆盖式的修改)
* @Anthor:孤傲苍狼
*
* @throws Exception
*/
@Test
public void blobModify() throws Exception {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
boolean defaultCommit = true;
try {
conn = JdbcUtils.getOracleConnection();
//得到数据库事务处理的默认提交方式
defaultCommit = conn.getAutoCommit();
//1、开启事务
conn.setAutoCommit(false);
//2、查询此BLOB对象并锁定。注意: 必 须加for update锁定该行,直至该行被修改完毕,保证不产生并发冲突
String sql = "SELECT BLOBCOL FROM TEST_BLOB WHERE ID=? FOR UPDATE";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 1);
rs = stmt.executeQuery();
if (rs.next()) {
//3、取出此BLOB对象 ,并强制转换成Oracle的BLOB对象
oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("BLOBCOL");
//4、使用IO向BLOB对象中写入数据
BufferedOutputStream out = new BufferedOutputStream(blob.getBinaryOutputStream());
BufferedInputStream in = new BufferedInputStream(JdbcOperaOracleBlob.class.getClassLoader().getResourceAsStream("02.jpg"));
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
in.close();
out.close();
}
//5、提交事务
conn.commit();
} catch (Exception ex) {
//6、出错回滚事务
conn.rollback();
throw ex;
} finally {
//8、恢复数据库事务处理的默认提交方式
conn.setAutoCommit(defaultCommit);
//释放资源
JdbcUtils.release(conn, stmt, rs);
}
}

/**
* @Method: blobReplace
* @Description:替换BLOB对象(将原BLOB对象清除,换成一个全新的BLOB对象)
* @Anthor:孤傲苍狼
*
* @throws Exception
*/
@Test
public void blobReplace() throws Exception {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
boolean defaultCommit = true;
try {
conn = JdbcUtils.getOracleConnection();
//得到数据库事务处理的默认提交方式
defaultCommit = conn.getAutoCommit();
//1、开启事务
conn.setAutoCommit(false);
//2、清空原BLOB对象
String sql = "UPDATE TEST_BLOB SET BLOBCOL=EMPTY_BLOB() WHERE ID=?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 1);
stmt.executeUpdate();
//3、查询此BLOB对象并锁定。注意: 必 须加for update锁定该行,直至该行被修改完毕,保证不产生并发冲突
sql = "SELECT BLOBCOL FROM TEST_BLOB WHERE ID=? FOR UPDATE";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 1);
rs = stmt.executeQuery();
if (rs.next()) {
//4、取出此BLOB对象 ,并强制转换成Oracle的BLOB对象
oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("BLOBCOL");
//5、使用IO向BLOB对象中写入数据
BufferedOutputStream out = new BufferedOutputStream(blob.getBinaryOutputStream());
BufferedInputStream in = new BufferedInputStream(JdbcOperaOracleBlob.class.getClassLoader().getResourceAsStream("01.jpg"));
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
in.close();
out.close();
}
//6、提交事务
conn.commit();
} catch (Exception ex) {
//7、出错回滚事务
conn.rollback();
throw ex;
} finally {
//8、恢复数据库事务处理的默认提交方式
conn.setAutoCommit(defaultCommit);
//释放资源
JdbcUtils.release(conn, stmt, rs);
}
}

/**
* @Method: blobRead
* @Description:BLOB对象读取
* @Anthor:孤傲苍狼
*
* @throws Exception
*/
@Test
public void blobRead() throws Exception {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
boolean defaultCommit = true;
try {
conn = JdbcUtils.getOracleConnection();
//得到数据库事务处理的默认提交方式
defaultCommit = conn.getAutoCommit();
//1、开启事务
conn.setAutoCommit(false);
//2、查询BLOB对象
String sql = "SELECT BLOBCOL FROM TEST_BLOB WHERE ID=?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 1);
rs = stmt.executeQuery();
if (rs.next()) {
//3、取出此BLOB对象 ,并强制转换成Oracle的BLOB对象
oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("BLOBCOL");
//4、以二进制流的形式输出
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("D:/1.jpg"));
BufferedInputStream in = new BufferedInputStream(blob.getBinaryStream());
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
in.close();
out.close();
}
//5、提交事务
conn.commit();
} catch (Exception ex) {
//6、出错回滚事务
conn.rollback();
throw ex;
} finally {
//8、恢复数据库事务处理的默认提交方式
conn.setAutoCommit(defaultCommit);
//释放资源
JdbcUtils.release(conn, stmt, rs);
}

}
}


四、使用JDBC处理Oracle大数据总结

  通过JDBC操纵Oracle数据库的LOB字段,不外乎插入、修改、替换、读取四种方式,掌握起来并不难。观察上述程序对LOB类型字段的存取,我们可以看出,较之其它类型字段,有下面几个显著不同的特点

  1、必须取消自动提交

  存取操作开始前,必须用setAutoCommit(false)取消自动提交。其它类型字段则无此特殊要求。这是因为存取LOB类型字段时,通常要进行多次操作可以完成。不这样的话,Oracle将抛出“读取违反顺序”的错误。

  2、插入方式不同

  LOB数据不能象其它类型数据一样直接插入(INSERT)。插入前必须先插入一个空的LOB对象,CLOB类型 的空对象为EMPTY_CLOB(),BLOB类型的空对象为EMPTY_BLOB()。之后通过SELECT命令查询得到先前插入的记录并锁定,继而将 空对象修改为所要插入的LOB对象。

  3、修改方式不同

  其它类型的字段修改时,用UPDATE … SET…命令即可。而LOB类型字段,则只能用SELECT … FOR UPDATE命令将记录查询出来并锁定,然后才能修改。且修改也有两种改法:一是在原数据基础上的修改(即覆盖式修改),执行SELECT … FOR UPDATE后再改数据;二是替换(先将原数据清掉,再修改),先执行UPDATE命令将LOB字段之值设为空的LOB对象,然后进行第一种改法。建议使 用替换的方法,以实现与其它字段UPDATE操作后一样的效果。

  4、存取时应使用由数据库JDBC驱动程序提供的LOB操作类

  对于Oracle数据库,应使用oracle.sql.CLOB和oracle.sql.BLOB。不使用由数据库JDBC驱动程序提供的LOB类时,程序运行时易于出现“抽象方法调用”的错误,这是因为JDBC所定义的java.sql.Clob与 java.sql.Blob接口,其中的一些方法并未在数据库厂家提供的驱动程序中真正实现。

  5、存取手段与文件操作相仿

  对于BLOB类型,应用InputStream/OutputStream类,此类不进行编码转换,逐个字节存取。oracle.sql.BLOB类相应提供了getBinaryStream()和getBinaryOutputStream()两个方法,前一个 方法用于读取Oracle的BLOB字段,后一个方法用于将数据写入Oracle的BLOB字段。

  对于CLOB类型,应用Reader/Writer类,此类进行编码转换。oracle.sql.CLOB类相应 提供了getCharacterStream()和getCharacterOutputStream()两个方法,前一个方法用于读取Oracle的 CLOB字段,后一个方法用于将数据写入Oracle的CLOB字段。

  需要说明的是,为了大幅提高程序执行效率,对BLOB/CLOB字段的读写操作,应该使用缓冲操作类(带 Buffered前缀),即:BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter。 例程中全部使用了缓冲操作类。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  sql jdbc oracle