JavaWeb使用JDBC处理Oracle大数据
一、Oracle中大数据处理
在Oracle中,LOB(LargeObject,大型对象)类型的字段现在用得越来越多了。因为这种类型的字段,容量大(最多能容纳4GB的数据),且一个表中可以有多个这种类型的字段,很灵活,适用于数据量非常大的业务领域(如图象、档案等)。
LOB类型分为BLOB和CLOB两种:BLOB即二进制大型对象(BinaryLargeObject),适用于存贮非文本的字节流数据(如程序、图象、影音等)。而CLOB,即字符型大型对象(CharacterLargeObject),则与字符集相关,适于存贮文本型的数据(如历史档案、大部头著作等)。
二、搭建测试环境
2.1、建立两个测试用的数据库表
建表SQL语句为:
1CREATETABLETEST_CLOB(IDNUMBER(3),CLOBCOLCLOB)
2
3CREATETABLETEST_BLOB(IDNUMBER(3),BLOBCOLBLOB)
2.2、搭建测试项目架构
2.3、编写db.properties配置文件
1oracleDb_Driver=oracle.jdbc.driver.OracleDriver
2oracleDb_Url=jdbc:oracle:thin:@localhost:1521:GACL
3oracleDb_UserName=GACL_XDP
4oracleDb_Password=P
2.4、编写JdbcUtils工具类
复制代码
1packageme.gacl.utils;
2
3importjava.io.InputStream;
4importjava.sql.Connection;
5importjava.sql.DriverManager;
6importjava.sql.ResultSet;
7importjava.sql.SQLException;
8importjava.sql.Statement;
9importjava.util.Properties;
10
11publicclassJdbcUtils{
12
13privatestaticStringoracleDb_Driver=null;
14privatestaticStringoracleDb_Url=null;
15privatestaticStringoracleDb_UserName=null;
16privatestaticStringoracleDb_Password=null;
17
18static{
19try{
20//读取db.properties文件中的数据库连接信息
21InputStreamin=JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
22Propertiesprop=newProperties();
23prop.load(in);
24
25//获取数据库连接驱动
26oracleDb_Driver=prop.getProperty("oracleDb_Driver");
27//获取数据库连接URL地址
28oracleDb_Url=prop.getProperty("oracleDb_Url");
29//获取数据库连接用户名
30oracleDb_UserName=prop.getProperty("oracleDb_UserName");
31//获取数据库连接密码
32oracleDb_Password=prop.getProperty("oracleDb_Password");
33
34//加载数据库驱动
35Class.forName(oracleDb_Driver);
36
37}catch(Exceptione){
38thrownewExceptionInInitializerError(e);
39}
40}
41
42/
43@Method:getOracleConnection
44@Description:获取Oracle数据库连接对象
45@Anthor:孤傲苍狼
46
47@returnConnection数据库连接对象
48@throwsSQLException
49/
50publicstaticConnectiongetOracleConnection()throwsSQLException{
51returnDriverManager.getConnection(oracleDb_Url,oracleDb_UserName,oracleDb_Password);
52}
53
54/
55@Method:release
56@Description:释放资源,
57要释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象
58@Anthor:孤傲苍狼
59
60@paramconn
61@paramst
62@paramrs
63/
64publicstaticvoidrelease(Connectionconn,Statementst,ResultSetrs){
65if(rs!=null){
66try{
67//关闭存储查询结果的ResultSet对象
68rs.close();
69}catch(Exceptione){
70e.printStackTrace();
71}
72rs=null;
73}
74if(st!=null){
75try{
76//关闭负责执行SQL命令的Statement对象
77st.close();
78}catch(Exceptione){
79e.printStackTrace();
80}
81}
82
83if(conn!=null){
84try{
85//关闭Connection数据库连接对象
86conn.close();
87}catch(Exceptione){
88e.printStackTrace();
89}
90}
91}
92}
复制代码
三、JDBC处理Oracle大数据
3.1、JDBC处理CLOB数据
复制代码
1packageme.gacl.demo;
2
3importjava.io.BufferedReader;
4importjava.io.BufferedWriter;
5importjava.io.FileReader;
6importjava.io.FileWriter;
7importjava.sql.Connection;
8importjava.sql.PreparedStatement;
9importjava.sql.ResultSet;
10importorg.junit.Test;
11importme.gacl.utils.JdbcUtils;
12
13/
14@ClassName:JdbcOperaOracleClob
15@Description:Oracle中字符型大型对象(CharacterLargeObject)数据处理
16@author:孤傲苍狼
17@date:2014-10-7下午3:53:19
18
19/
20publicclassJdbcOperaOracleClob{
21
22/
23CREATETABLETEST_CLOB(IDNUMBER(3),CLOBCOLCLOB)
24/
25/
26@Method:clobInsert
27@Description:往数据库中插入一个新的CLOB对象
28@Anthor:孤傲苍狼
29
30@throwsException
31/
32@Test
33publicvoidclobInsert()throwsException{
34Connectionconn=null;
35PreparedStatementstmt=null;
36ResultSetrs=null;
37conn=JdbcUtils.getOracleConnection();
38booleandefaultCommit=conn.getAutoCommit();
39/开启事务,设定不自动提交/
40conn.setAutoCommit(false);
41try{
42/插入一个空的CLOB对象/
43Stringsql="INSERTINTOTEST_CLOBVALUES(?,EMPTY_CLOB())";
44stmt=conn.prepareStatement(sql);
45stmt.setInt(1,1);
46stmt.executeUpdate();
47/查询此CLOB对象并锁定/
48sql="SELECTCLOBCOLFROMTEST_CLOBWHEREID=?FORUPDATE";
49stmt=conn.prepareStatement(sql);
50stmt.setInt(1,1);
51rs=stmt.executeQuery();
52if(rs.next()){
53/取出此CLOB对象/
54oracle.sql.CLOBclob=(oracle.sql.CLOB)rs.getClob("CLOBCOL");
55/向CLOB对象中写入数据/
56BufferedWriterout=newBufferedWriter(clob.getCharacterOutputStream());
57//这种方式获取的路径,其中的空格会被使用“%20”代替
58Stringpath=JdbcOperaClob.class.getClassLoader().getResource("data.txt").getPath();
59//将“%20”替换回空格
60path=path.replaceAll("%20","");
61BufferedReaderin=newBufferedReader(newFileReader(path));
62intc;
63while((c=in.read())!=-1){
64out.write(c);
65}
66in.close();
67out.close();
68}
69/正式提交/
70conn.commit();
71System.out.println("插入成功");
72}catch(Exceptionex){
73/出错回滚/
74conn.rollback();
75throwex;
76}finally{
77/恢复原提交状态/
78conn.setAutoCommit(defaultCommit);
79JdbcUtils.release(conn,stmt,rs);
80}
81
82}
83
84/
85@Method:clobRead
86@Description:CLOB对象读取
87@Anthor:孤傲苍狼
88
89@throwsException
90/
91@Test
92publicvoidclobRead()throwsException{
93Connectionconn=null;
94PreparedStatementstmt=null;
95ResultSetrs=null;
96conn=JdbcUtils.getOracleConnection();
97booleandefaultCommit=conn.getAutoCommit();
98conn.setAutoCommit(false);
99try{
100/查询CLOB对象/
101Stringsql="SELECTFROMTEST_CLOBWHEREID=?";
102stmt=conn.prepareStatement(sql);
103stmt.setInt(1,1);
104rs=stmt.executeQuery();
105if(rs.next()){
106/获取CLOB对象/
107oracle.sql.CLOBclob=(oracle.sql.CLOB)rs.getClob("CLOBCOL");
108/以字符形式输出/
109BufferedReaderin=newBufferedReader(clob.getCharacterStream());
110BufferedWriterout=newBufferedWriter(newFileWriter("D:\\2.txt"));
111intc;
112while((c=in.read())!=-1){
113out.write(c);
114}
115out.close();
116in.close();
117}
118}catch(Exceptionex){
119conn.rollback();
120throwex;
121}finally{
122/恢复原提交状态/
123conn.setAutoCommit(defaultCommit);
124JdbcUtils.release(conn,stmt,rs);
125}
126}
127
128/
129@Method:clobModify
130@Description:修改CLOB对象(是在原CLOB对象基础上进行覆盖式的修改)
131@Anthor:孤傲苍狼
132
133@throwsException
134/
135@Test
136publicvoidclobModify()throwsException{
137Connectionconn=null;
138PreparedStatementstmt=null;
139ResultSetrs=null;
140conn=JdbcUtils.getOracleConnection();
141booleandefaultCommit=conn.getAutoCommit();
142//开启事务
143conn.setAutoCommit(false);
144try{
145/查询CLOB对象并锁定/
146Stringsql="SELECTCLOBCOLFROMTEST_CLOBWHEREID=?FORUPDATE";
147stmt=conn.prepareStatement(sql);
148stmt.setInt(1,1);
149rs=stmt.executeQuery();
150if(rs.next()){
151/获取此CLOB对象/
152oracle.sql.CLOBclob=(oracle.sql.CLOB)rs.getClob("CLOBCOL");
153/进行覆盖式修改/
154BufferedWriterout=newBufferedWriter(clob.getCharacterOutputStream());
155//这种方式获取的路径,其中的空格会被使用“%20”代替
156Stringpath=JdbcOperaClob.class.getClassLoader().getResource("data2.txt").getPath();
157//将“%20”替换回空格
158path=path.replaceAll("%20","");
159BufferedReaderin=newBufferedReader(newFileReader(path));
160intc;
161while((c=in.read())!=-1){
162out.write(c);
163}
164in.close();
165out.close();
166}
167/提交事务/
168conn.commit();
169}catch(Exceptionex){
170/出错回滚事务/
171conn.rollback();
172throwex;
173}finally{
174/恢复原提交状态/
175conn.setAutoCommit(defaultCommit);
176JdbcUtils.release(conn,stmt,rs);
177}
178}
179
180/
181@Method:clobReplace
182@Description:替换CLOB对象(将原CLOB对象清除,换成一个全新的CLOB对象)
183@Anthor:孤傲苍狼
184
185@throwsException
186/
187@Test
188publicvoidclobReplace()throwsException{
189Connectionconn=null;
190PreparedStatementstmt=null;
191Resuwww.wang027.comltSetrs=null;
192conn=JdbcUtils.getOracleConnection();
193booleandefaultCommit=conn.getAutoCommit();
194//开启事务
195conn.setAutoCommit(false);
196try{
197/清空原CLOB对象/
198Stringsql="UPDATETEST_CLOBSETCLOBCOL=EMPTY_CLOB()WHEREID=?";
199stmt=conn.prepareStatement(sql);
200stmt.setInt(1,1);
201stmt.executeUpdate();
202
203/查询CLOB对象并锁定/
204sql="SELECTCLOBCOLFROMTEST_CLOBWHEREID=?FORUPDATE";
205stmt=conn.prepareStatement(sql);
206stmt.setInt(1,1);
207rs=stmt.executeQuery();
208if(rs.next()){
209/获取此CLOB对象/
210oracle.sql.CLOBclob=(oracle.sql.CLOB)rs.getClob("CLOBCOL");
211/更新数据/
212BufferedWriterout=newBufferedWriter(clob.getCharacterOutputStream());
213//这种方式获取的路径,其中的空格会被使用“%20”代替
214Stringpath=JdbcOperaClob.class.getClassLoader().getResource("db.properties").getPath();
215//将“%20”替换回空格
216path=path.replaceAll("%20","");
217BufferedReaderin=newBufferedReader(newFileReader(path));
218intc;
219while((c=in.read())!=-1){
220out.write(c);
221}
222in.close();
223out.close();
224}
225/正式提交/
226conn.commit();
227}catch(Exceptionex){
228/出错回滚/
229conn.rollback();
230throwex;
231}finally{
232/恢复原提交状态/
233conn.setAutoCommit(defaultCommit);
234JdbcUtils.release(conn,stmt,rs);
235}
236}
237}
复制代码
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:insertintotestblob(id,image)values(?,empty_blob())
2、获得blob的cursor:
selectimagefromtestblobwhereid=?forupdate注意:必须加forupdate锁定该行,直至该行被修改完毕,保证不产生并发冲突。
Blobb=rs.getBlob("image");
3、利用io和获取到的cursor往数据库读写数据
注意:以上操作需开启事务。
BLOB对象的存取范例
复制代码
1packageme.gacl.demo;
2
3importjava.io.BufferedInputStream;
4importjava.io.BufferedOutputStream;
5importjava.io.FileOutputStream;
6importjava.sql.Connection;
7importjava.sql.PreparedStatement;
8importjava.sql.ResultSet;
9importorg.junit.Test;
10importme.gacl.utils.JdbcUtils;
11
12/
13@ClassName:JdbcOperaOracleBlob
14@Description:Oracle中大数据处理
15@author:孤傲苍狼
16@date:2014-10-7下午3:53:19
17
18/
19publicclassJdbcOperaOracleBlob{
20
21/
22@Method:blobInsert
23@Description:向数据库中插入一个新的BLOB对象
24@Anthor:孤傲苍狼
25
26@throwsException
27/
28@Test
29publicvoidblobInsert()throwsException{
30Connectionconn=null;
31PreparedStatementstmt=null;
32ResultSetrs=null;
33booleandefaultCommit=true;
34try{
35conn=JdbcUtils.getOracleConnection();
36//得到数据库事务处理的默认提交方式
37defaultCommit=conn.getAutoCommit();
38//1、开启事务
39conn.setAutoCommit(false);
40//2、插入一个空的BLOB对象
41Stringsql="INSERTINTOTEST_BLOBVALUES(?,EMPTY_BLOB())";
42stmt=conn.prepareStatement(sql);
43stmt.setInt(1,1);
44stmt.executeUpdate();
45//3、查询此BLOB对象并锁定。注意:必须加forupdate锁定该行,直至该行被修改完毕,保证不产生并发冲突
46sql="SELECTBLOBCOLFROMTEST_BLOBWHEREID=?FORUPDATE";
47stmt=conn.prepareStatement(sql);
48stmt.setInt(1,1);
49rs=stmt.executeQuery();
50if(rs.next()){
51//4、取出此BLOB对象,并强制转换成Oracle的BLOB对象
52oracle.sql.BLOBblob=(oracle.sql.BLOB)rs.getBlob("BLOBCOL");
53//5、使用IO向BLOB对象中写入数据
54BufferedOutputStreamout=newBufferedOutputStream(blob.getBinaryOutputStream());
55BufferedInputStreamin=newBufferedInputStream(JdbcOperaOracleBlob.class.getClassLoader().getResourceAsStream("01.jpg"));
56intc;
57while((c=in.read())!=-1){
58out.write(c);
59}
60in.close();
61out.close();
62}
63//6、提交事务
64conn.commit();
65}catch(Exceptionex){
66//7、出错回滚事务
67conn.rollback();
68throwex;
69}finally{
70//8、恢复数据库事务处理的默认提交方式
71conn.setAutoCommit(defaultCommit);
72//释放资源
73JdbcUtils.release(conn,stmt,rs);
74}
75
76}
77
78/
79@Method:blobModify
80@Description:修改BLOB对象(是在原BLOB对象基础上进行覆盖式的修改)
81@Anthor:孤傲苍狼
82
83@throwsException
84/
85@Test
86publicvoidblobModify()throwsException{
87Connectionconn=null;
88PreparedStatementstmt=null;
89ResultSetrs=null;
90booleandefaultCommit=true;
91try{
92conn=JdbcUtils.getOracleConnection();
93//得到数据库事务处理的默认提交方式
94defaultCommit=conn.getAutoCommit();
95//1、开启事务
96conn.setAutoCommit(false);
97//2、查询此BLOB对象并锁定。注意:必须加forupdate锁定该行,直至该行被修改完毕,保证不产生并发冲突
98Stringsql="SELECTBLOBCOLFROMTEST_BLOBWHEREID=?FORUPDATE";
99stmt=conn.prepareStatement(sql);
100stmt.setInt(1,1);
101rs=stmt.executeQuery();
102if(rs.next()){
103//3、取出此BLOB对象,并强制转换成Oracle的BLOB对象
104oracle.sql.BLOBblob=(oracle.sql.BLOB)rs.getBlob("BLOBCOL");
105//4、使用IO向BLOB对象中写入数据
106BufferedOutputStreamout=newBufferedOutputStream(blob.getBinaryOutputStream());
107BufferedInputStreamin=newBufferedInputStream(JdbcOperaOracleBlob.class.getClassLoader().getResourceAsStream("02.jpg"));
108intc;
109while((c=in.read())!=-1){
110out.write(c);
111}
112in.close();
113out.close();
114}
115//5、提交事务
116conn.commit();
117}catch(Exceptionex){
118//6、出错回滚事务
119conn.rollback();
120throwex;
121}finally{
122//8、恢复数据库事务处理的默认提交方式
123conn.setAutoCommit(defaultCommit);
124//释放资源
125JdbcUtils.release(conn,stmt,rs);
126}
127}
128
129/
130@Method:blobReplace
131@Description:替换BLOB对象(将原BLOB对象清除,换成一个全新的BLOB对象)
132@Anthor:孤傲苍狼
133
134@throwsException
135/
136@Test
137publicvoidblobReplace()throwsException{
138Connectionconn=null;
139PreparedStatementstmt=null;
140ResultSetrs=null;
141booleandefaultCommit=true;
142try{
143conn=JdbcUtils.getOracleConnection();
144//得到数据库事务处理的默认提交方式
145defaultCommit=conn.getAutoCommit();
146//1、开启事务
147conn.setAutoCommit(false);
148//2、清空原BLOB对象
149Stringsql="UPDATETEST_BLOBSETBLOBCOL=EMPTY_BLOB()WHEREID=?";
150stmt=conn.prepareStatement(sql);
151stmt.setInt(1,1);
152stmt.executeUpdate();
153//3、查询此BLOB对象并锁定。注意:必须加forupdate锁定该行,直至该行被修改完毕,保证不产生并发冲突
154sql="SELECTBLOBCOLFROMTEST_BLOBWHEREID=?FORUPDATE";
155stmt=conn.prepareStatement(sql);
156stmt.setInt(1,1);
157rs=stmt.executeQuery();
158if(rs.next()){
159//4、取出此BLOB对象,并强制转换成Oracle的BLOB对象
160oracle.sql.BLOBblob=(oracle.sql.BLOB)rs.getBlob("BLOBCOL");
161//5、使用IO向BLOB对象中写入数据
162BufferedOutputStreamout=newBufferedOutputStream(blob.getBinaryOutputStream());
163BufferedInputStreamin=newBufferedInputStream(JdbcOperaOracleBlob.class.getClassLoader().getResourceAsStream("01.jpg"));
164intc;
165while((c=in.read())!=-1){
166out.write(c);
167}
168in.close();
169out.close();
170}
171//6、提交事务
172conn.commit();
173}catch(Exceptionex){
174//7、出错回滚事务
175conn.rollback();
176throwex;
177}finally{
178//8、恢复数据库事务处理的默认提交方式
179conn.setAutoCommit(defaultCommit);
180//释放资源
181JdbcUtils.release(conn,stmt,rs);
182}
183}
184
185/
186@Method:blobRead
187@Description:BLOB对象读取
188@Anthor:孤傲苍狼
189
190@throwsException
191/
192@Test
193publicvoidblobRead()throwsException{
194Connectionconn=null;
195PreparedStatementstmt=null;
196ResultSetrs=null;
197booleandefaultCommit=true;
198try{
199conn=JdbcUtils.getOracleConnection();
200//得到数据库事务处理的默认提交方式
201defaultCommit=conn.getAutoCommit();
202//1、开启事务
203conn.setAutoCommit(false);
204//2、查询BLOB对象
205Stringsql="SELECTBLOBCOLFROMTEST_BLOBWHEREID=?";
206stmt=conn.prepareStatement(sql);
207stmt.setInt(1,1);
208rs=stmt.executeQuery();
209if(rs.next()){
210//3、取出此BLOB对象,并强制转换成Oracle的BLOB对象
211oracle.sql.BLOBblob=(oracle.sql.BLOB)rs.getBlob("BLOBCOL");
212//4、以二进制流的形式输出
213BufferedOutputStreamout=newBufferedOutputStream(newFileOutputStream("D:/1.jpg"));
214BufferedInputStreamin=newBufferedInputStream(blob.getBinaryStream());
215intc;
216while((c=in.read())!=-1){
217out.write(c);
218}
219in.close();
220out.close();
221}
222//5、提交事务
223conn.commit();
224}catch(Exceptionex){
225//6、出错回滚事务
226conn.rollback();
227throwex;
228}finally{
229//8、恢复数据库事务处理的默认提交方式
230conn.setAutoCommit(defaultCommit);
231//释放资源
232JdbcUtils.release(conn,stmt,rs);
233}
234
235}
236}
复制代码
四、使用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…FORUPDATE命令将记录查询出来并锁定,然后才能修改。且修改也有两种改法:一是在原数据基础上的修改(即覆盖式修改),执行SELECT…FORUPDATE后再改数据;二是替换(先将原数据清掉,再修改),先执行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。例程中全部使用了缓冲操作类。
|
|