在Oracle中,LOB(Large Object,大型对象)类型的字段现在用得越来越多了。因为这种类型的字段,容量大(最多能容纳4GB的数据),且一个表中可以有多个这种类型的字段,很灵活,适用于数据量非常大的业务领域(如图象、档案等)。而LONG、LONG RAW等类型的字段,虽然存储容量也不小(可达2GB),但由于一个表中只能有一个这样类型的字段的限制,现在已很少使用了。
Oracle中若以字符串的形式写入数据到Clob字段中,默认的长度为4000,最大可存储4G。
直接将字符串写入Clob字段中,则最大可写4000个字节;若要写入大的字符数据,可以将字符数据以二进制流的形式写入。
网上有人贴出的clobsetCharacterStream()写入方法,可以运行,但是无法突破字符数限制,字符数超出就直接为null,故果断抛弃。
Reader clobReader = new StringReader(MyText); // 转成流形式
pstmt.setCharacterStream(3, clobReader, MyText.getBytes("GBK").length);
正确方法如下:
写入的时候有三部,第一先插入一个空的empty_clob(),然后获得这个cursor,然后再修改,这要牵涉到IO流的操作。。。
- package com.cs.utils;
-
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.io.Reader;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
-
- import oracle.sql.CLOB;
-
-
-
-
-
-
- public class ClobTest {
-
- private static Connection conn=null;
-
- private static PreparedStatement ps=null;
-
- private static ResultSet rst=null;
-
- static{
- try {
- Class.forName("oracle.jdbc.driver.OracleDriver");
- conn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:WMG", "hibernate","hibernate");
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
-
-
-
-
-
-
- public boolean inserClob(String userid, String strClob){
- boolean suc=false;
- CLOB clob=null;
-
-
- String sql="INSERT into test_clob(userid,clob_test) VALUES(?,empty_clob())";
- try {
-
- conn.setAutoCommit(false);
- ps=conn.prepareStatement(sql);
- ps.setString(1, userid);
- ps.executeUpdate();
- ps.close();
-
-
- sql="SELECT clob_test FROM test_clob WHERE userid=? for update";
- ps=conn.prepareStatement(sql);
- ps.setString(1, userid);
- rst=ps.executeQuery();
- if(rst.next()){
- clob=(CLOB)rst.getClob(1);
- }
-
- PrintWriter pw=new PrintWriter(clob.getCharacterOutputStream());
- pw.write(strClob);
-
- pw.flush();
- ps.close();
-
-
- sql="UPDATE test_clob set clob_test =? where userid=?";
- ps=conn.prepareStatement(sql);
- ps.setClob(1, clob);
- ps.setString(2, userid);
- ps.executeUpdate();
- ps.close();
- conn.commit();
- pw.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
-
- return suc;
- }
-
-
-
-
- public String readClob(String userid){
- String test_clob="";
- CLOB clob=null;
- StringBuffer sb=new StringBuffer();
- String sql="SELECT * FROM test_clob WHERE userid='"+userid+"'";
- try {
- ps=conn.prepareStatement(sql);
- rst=ps.executeQuery();
- if(rst.next()){
- clob=(CLOB)rst.getClob(2);
- }
- Reader reader=clob.getCharacterStream();
- char[] buffer=new char[1024];
- int length=0;
- while((length=reader.read(buffer))!=-1){
- sb.append(buffer, 0, length);
- }
- } catch (SQLException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- test_clob=sb.toString();
- return test_clob;
- }
- public static void main(String[] args){
- new ClobTest().inserClob("4","我是Clob,出来了哈哈哈");
- String test=new ClobTest().readClob("4");
- System.out.println(test);
- }
- }
具体来说,对于一般数据操作有insert、updata两种:
(1)updata操作,可以获取现成的id,找到指定clob字段更新。只需要做第二、三步。
(2)insert操作,因是新插入的数据,故id未定(同时可能有很多插入操作)第一步可以与其他字段一起insert,但是第二、三步,如何取得生成的id呢?通过查询序列器,会不会得不到当前这条数据的id?
辛亏数据字段里有一个是时间戳ctime,我就用ctime 去select id了。暂且将就着吧!望高人提供更正确的方法。
- Select TO_CHAR(SEQ_ID.nextval) ID FROM DUAL