java存取oracle中的COLB类型数据

 一、如何去处理ClobBLOB的大类型

  CLOB可用于存放大文本数据,最多可存储4GB数据,在应用开发中比较常见.java提供的sql.Clob类与之对应.它提供两个方法来读取Clob的数据:

  getCharacterStream() 方法返回按unicode编码的输入流(java.io.Reader对象)

  getAsciiStream() 方法返回按ASCII编码的输入流(java.io.InputStream对象)

  所以如果你的数据库中有可能存储中文字符的话,就要使用前一个方法.

  现在举一个实际的例子,让我一步步学习如何使用CLOB.

  首先,创建一个含CLOB字段的表:

  create table test (id INTEGER,content clob);

  接下来, 我们通过JSP往这张表里插入一条记录,然后再获取显示它.

  插入操作:

  以上需要注意的几点是:

  1)clob类型的数据不能直接insert,要先通过empty_clob()方法给它分配一个locator(同理,blob的用empty_blob()函数分配locator).然后把它select出来(此时它当然没有数据,但结果集不是空的),得到一个Clob的对象,修改该对象的内容让它满足我们的需要,再通过update方法更新该行记录.

  2) 通过select修改含lob类型的记录时一定要锁定该行(通过for update关键字实现),否则oracle会报错.

  3) 刚插入的记录就select for update, 会出现"违反读取顺序"错误,解决办法是将自动提交功能置为false,即不允许自动提交,然后commit它,再select,就可以了. 这就是上面那段代码里//*两行的作用.

  下面,我们将刚插入的记录从数据库中读取出来并显示之:

  二、编码问题

  因为JAVA的开发者是老外,所以他们对中文的支持并不是太好,这一点让不少的我们感到很是头痛,也就是我们通过说的汉字编码问题吧,关于一些汉字编码的规范我就不多说了,我主要是谈谈在和oracle数据库连接时的一些小问题,不过这些小问题很是让人头痛的。

  1、在插入到数据库中的中文问题要转换成编码

  2、从数据库中读到中文又要转换成编码

  让我们看一个编码的JAVA代码:

//ECov.java
  import java.io.UnsupportedEncodingException;
  public class ECov
  {
  public static String asc2gb(String asc){
  String ret;
  if(asc==null)return asc;
  try{
  ret=new String(asc.getBytes("ISO8859_1"),"GB2312");
  }
  catch(UnsupportedEncodingException e){
  ret=asc;
  }
  return ret;
  }
  public static String gb2asc(String gb){
  String ret;
  if(gb==null)return gb;
  try{
  ret=new String(gb.getBytes("GB2312"),"ISO8859_1");
  }
  catch(UnsupportedEncodingException e){
  ret=gb;
  }
  return ret;
  }
  public static int byte2int(byte b){
  return ((-1)>>>24)&b;
  }
  }

  其实这段代码的意思也就是把两种方法合而为一了。

  在进行数据库插入时要用ECov.gb2asc(arg),要在读时要用ECov.asc2gb(arg)。其中最关键的一点就是Oracle好像只认识ISO8859_1这种格式的编码吧(仅是我的想法)。

  三、一些小细节

  1、就是setAutoCommit(true or false),就是我们在sqlPlus中常用commit()的功能,如果是用true,就不要用commit(),否则还是用commit()方法的。

  2、对日期类型的处理,其实他并不是想象中setDate(),getDate()那么简单的,中间有很大的漏洞。大家自己多调试就会觉得有很多的乐趣的。

  3、在和数据库中最好是采用连接池技术,用标准的J2EE的环境,用简单的JNDI技术,是很好的一种方法的。

共2页。 首页 上一页1 2

 

 

 

 

 

 

*操作oracle数据库的CLOB字段,包括读和写
*作者:令少爷
* */

package com.nes.common.sql.lob;

import java.sql.*;
import java.io.*;
import oracle.jdbc.OracleResultSet;
import oracle.sql.*;

public class JClob {

String tableName = null; //表名
String primaryKey = null; //表的主键名
String primaryValue = null; //表的主键值
String fieldName = null; //表的CLOB字段名
String clobValue = null; //表的CLOB字段值

Connection conn = null; //与oracle的连接

/**
*
*用于测试用
*
* */
public static void main(String[] args) {
try {
JClob jc = newJClob(getConnection(),"aa","a","aaaa","c","ccc");
jc.write();
jc.read();
}
catch (Exception e) {
System.out.println(e);
e.printStackTrace();
}
}


/**
*
*构造方法
*
* */
public JClob(Connection connection,String tableName,String primaryKey,StringprimaryValue,String fieldName,String clobValue) {
this.conn = connection;
this.tableName = tableName;
this.primaryKey = primaryKey;
this.primaryValue = primaryValue;
this.fieldName = fieldName;
this.clobValue = clobValue;
}

/**
*
*构造方法,但不必传clobValue值
*一般构造出的实例用来读Clob字段
*
* */
public JClob(Connection connection,String tableName,String primaryKey,StringprimaryValue,String fieldName) {
this.conn = connection;
this.tableName = tableName;
this.primaryKey = primaryKey;
this.primaryValue = primaryValue;
this.fieldName = fieldName;
}

/**
*
*用于测试
*
* */
public static Connection getConnection() throwsSQLException,ClassNotFoundException {
Class.forName("oracle.jdbc.OracleDriver");
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@192.168.1.18:1521:portal","portal","portal");
return conn;
}

/**
*
*读数据库中clob字段的内容
*@return clob字段值
*
* */
public String read() throws SQLException,IOException {
String rtn = null;
try {
String sql = "select " + fieldName + " from " + tableName +" where " + primaryKey + "=" + primaryValue;
//Connection conn = getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
//int v = Integer.parseInt(primaryValue);
//pstmt.setInt(1,v);
ResultSet rs = pstmt.executeQuery();

java.sql.Clob clob = null;
if (rs.next()) {
clob = rs.getCLOB(fieldName);
//clob = ((OracleResultSet)rs).getCLOB(fieldName);
//clob = ((org.apache.commons.dbcp.DelegatingResultSet)rs).getClob(fieldName);
//Reader in = clob.getCharacterStream();
InputStream input = clob.getAsciiStream();
int len = (int)clob.length();
byte[] by = new byte[len];
int i ;//= input.read(by,0,len);
while(-1 != (i = input.read(by, 0, by.length))) {
input.read(by, 0, i);
}
rtn = new String(by);
}
}
catch (SQLException e){
throw e;
}
catch (Exception ee) {
ee.printStackTrace();
}

return rtn;
}

/**
*
*葱数据库中clob字段的内容
*
* */
public void write() throws SQLException,IOException {
String sql = "update " + tableName + " set " + fieldName +"=empty_clob() where " + primaryKey + "=" + primaryValue;
//Connection conn = getConnection();
conn.setAutoCommit(false);

PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.executeUpdate();

sql = "select " + fieldName + " from "+ tableName + " where " + primaryKey + "=" + primaryValue;
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql);

java.sql.Clob clob ;
if (rs.next()) {
clob = ((oracle.jdbc.OracleResultSet)rs).getClob(fieldName);
//clob=((org.apache.commons.dbcp.DelegatingResultSet)rs).getClob(fieldName);
oracle.sql.CLOB my_clob = (oracle.sql.CLOB)clob;
OutputStream writer = my_clob.getAsciiOutputStream();
byte[] contentStr = this.getContent().getBytes();
writer.write(contentStr);
writer.flush();
writer.close();
}

conn.commit();
rs.close();
st.close();
pstmt.close();
conn.setAutoCommit(true);
}

/**
*
*
* */
private String getContent() {
return this.clobValue;
}

/**
*
*
* */
public void setClobValue(String clobValue) {
this.clobValue = clobValue;
}
}

 

 

 

 

 

 

字段类型:blob,clob,nclob
  说明:三种大型对象(LOB),用来保存较大的图形文件或带格式的文本文件,如Miceosoft Word文档,以及音频、视频等非文本文件,最大长度是4GB。LOB有几种类型,取决于你使用的字节的类型,Oracle 8i实实在在地将这些数据存储在数据库内部保存。可以执行读取、存储、写入等特殊操作。
  
  我们所操作的clobtest_table中属性是(字符型id,CLOB型picstr),目前我们假设一个大的字符对象str已经包含了我们需要存入picstr字段的数据。而且connection对象conn已经建立。以下的例子程序也因为不想占用太多的空间,所以对抛出异常没有写。大家参考一下api doc。就可以知道该抛出什么异常了,此处仅仅告诉大家如何去写。
 
  代码:  
  (1)对数据库clob型执行插入操作
  *************************************************
  
  java.sql.PreparedStatement pstmt = null;
  ResultSet rs = null;
  String query = "";
  
  conn.setAutoCommit(false); www@bitscn@com
   query = "insert intoclobtest_table(id,picstr) values(?,empty_clob())";
  java.sql.PreparedStatement pstmt =conn.prepareStatement(query);
  pstmt.setString(1,"001");
  pstmt.executeUpdate();
  pstmt = null
   query = "select picstr from clobtest_tablewhere id = '001' for update";
  pstmt = con.prepareStatement(query)
  rs= pstmt.executeQuery();
  
  oracle.sql.CLOB clobtt = null;
  if(rs.next()){
   clobtt = (oracle.sql.CLOB)rs.getClob(1);
  }
  Writer wr = clobtt.getCharacterOutputStream();
  wr.write(strtmp);
  wr.flush();
  wr.close();
  rs.close();
  con.commit();
  
  
  
  (2)通过sql/plus查询是否已经成功插入数据库
  *************************************************
  
  PL/SQL的包DBMS_LOB来处理LOB数据。察看刚才的插入是否成功。使用DBMS_LOB包的getlength这个procedure来检测是否已经将str存入到picstr字段中了。如:bitsCN.nET*中国网管博客
  
  SQL> select dbms_lob.getlength(picstr) fromclobtest_table;
  
  
  (3)对数据库clob型执行读取操作
  *************************************************
  
  读取相对插入就很简单了。基本步骤和一半的取数据库数据没有太大的差别。
  String description = ""
   query = "select picstr from clobtest_tablewhere id = '001'";
  pstmt = con.prepareStatement(query);
  ResultSet result = pstmt.executeQuery();
  if(result.next()){
   oracle.jdbc.driver.OracleResultSet ors =
   (oracle.jdbc.driver.OracleResultSet)result;
   oracle.sql.CLOB clobtmp = (oracle.sql.CLOB)ors.getClob(1);
  
   if(clobtmp==null || clobtmp.length()==0){
   System.out.println("======CLOB对象为空 ");
   description = "";
   }else{
  description=clobtmp.getSubString((long)1,(int)clobtmp.length()); BBS.bitsCN.com网管论坛
   System.out.println("======字符串形式 "+description);
   }
  }

[/size]程序示例:

Java代码

  1. public void getTpxw() {   
  2.         Session session = HibernateUtil.currentSession();   
  3.         Transaction tx = session.beginTransaction();   
  4.         Query q = session   
  5.                 .createQuery("select infos.guId, infos.subject,infos.content from Infos as infos,Category as category "  
  6.                         + "where (category.categoryName='视频介绍') and (infos.categoryId=category.guId) "  
  7.                         + "order by infos.startDate desc ");   
  8.         q.setFirstResult(0);   
  9.         q.setMaxResults(1);   
  10.         Iterator list = q.list().iterator();   
  11.         Infos infosCustom = null;   
  12.         if (list.hasNext()) {   
  13.             Object[] it = (Object[]) list.next();   
  14.             infosCustom = new Infos();   
  15.             infosCustom.setGuId((String) it[0]);   
  16.             String sub = (String) it[1];   
  17.             // String content = (String) it[2];   
  18.             infosCustom.setSubject(sub);   
  19.   
  20.             try {   
  21.                 SerializableClob bookCol = (SerializableClob) it[2];   
  22.                 Clob jbookColClob = bookCol.getWrappedClob();   
  23.                 CLOB oClob = (CLOB) jbookColClob;   
  24.                 Reader in = oClob.characterStreamValue();   
  25.                 char b[] = new char[8192];   
  26.                 StringBuffer str = new StringBuffer();   
  27.                 long totalSize = 0;   
  28.                 long fileLength = jbookColClob.length();   
  29.                 int ii = 0;   
  30.                 if (fileLength < 8192) {   
  31.                     ii = in.read(b, 0, (int) fileLength);   
  32.   
  33.                     str.append(b);   
  34.                 } else  
  35.                     while (totalSize < fileLength) {   
  36.                         ii = in.read(b, 08192);   
  37.                         totalSize += ii;   
  38.                         str.append(b);   
  39.                     }   
  40.                 in.close();   
  41.                 infosCustom.setBookColS(str.toString());   
  42.                 String content = str.toString();   
  43.                 if (content != null) {   
  44.                     if (content.length() <= Integer   
  45.                             .parseInt(getContentLength()))   
  46.                         infosCustom.setBookColS(content);   
  47.                     else  
  48.                         infosCustom.setBookColS(content.substring(0, Integer   
  49.                                 .parseInt(getContentLength()))   
  50.                                 + "......");   
  51.                 }   
  52.             } catch (Exception e) {   
  53.                 e.printStackTrace();   
  54.             }   
  55.         } else {   
  56.             infosCustom = new Infos();   
  57.             infosCustom.setBookColS("没有相关内容");   
  58.         }   
  59.         setCurrentTpxw(infosCustom);   
  60.         tx.commit();   
  61.         HibernateUtil.closeSession();   
  62.     }  

 

 

 

 

 

 

 

 

 

相关文章:  


推荐圈子: liferay
更多相关推荐

Blob是指二进制大对象也就是英文Binary Large Object的所写,而Clob是指大字符对象也就是英文Character Large Object的所写。由此可见这辆个类型都是用来存储大量数据而设计的,其中BLOB是用来存储大量二进制数据的;CLOB用来存储大量文本数据。
那么有人肯定要问既然已经有VARCHAR和VARBINARY两中类型,为什么还要再使用另外的两种类型呢?其实问题很简单,VARCHAR和VARBINARY两种类型是有自己的局限性的。首先说这两种类型的长度还是有限的不可以超过一定的限额,以VARCHAR再ORA中为例长度不可以超过4000;那么有人又要问了,LONGVARCHAR类型作为数据库中的一种存储字符的类型可以满足要求,存储很长的字符,那为什么非要出现CLOB类型呢?其实如果你用过LONGVARCHAR类型就不难发现,该类型的一个重要缺陷就是不可以使用LIKE这样的条件检索。(稍候将介绍在CLOB中如何实现类似LIKE的模糊查找)另外除了上述的问题外,还又一个问题,就是在数据库中VARCHAR和VARBINARY的存取是将全部内容从全部读取或写入,对于100K或者说更大数据来说这样的读写方式,远不如用流进行读写来得更现实一些。
在JDBC中有两个接口对应数据库中的BLOB和CLOB类型,java.sql.Blob和java.sql.Clob。和你平常使用数据库一样你可以直接通过ResultSet.getBlob()方法来获取该接口的对象。与平时的查找唯一不同的是得到Blob或Clob的对象后,我们并没有得到任何数据,但是我们可以这两个接口中的方法得到数据
例如:
Blob b=resultSet.getBlob(1);
InputStream bin=b.getBinaryStryeam();
Clob c=resultSet.getClob(2);
Reader cReader=c.getCharacterStream():
关于Clob类型的读取可以使用更直接的方法,就是直接通过ResultSet.getCharacterStream();方法获得字符流,但该方法并不安全,所以建议还是使用上面例子的方法获取Reader。
另外还有一种获取方法,不使用数据流,而是使用数据块。
例如
Blob b=resultSet.getBlob(1);
byte data=b.getByte(0,b.length());
Clob c=resultSet.getClob(2);
String str=c.getSubString(0,c.length()):
在这里我要说明一下,这个方法其实并不安全,如果你很细心的话,那很容易就能发现getByte()和getSubString()两个方法中的第二个参数都是int类型的,而BLOB和CLOB是用来存储大量数据的。而且Bolb.length()和Clob.length()的返回值都是long类型的,所以很不安全。这里不建议使用。但为什么要在这里提到这个方法呢?稍候告诉你答案,这里你需要记住使用数据块是一种方法。

在存储的时候也同样的在PreparedStatement和CallableStatememt中,以参数的形式使用setBlob()和setClob方法把Blob和Clob对象作为参数传递给SQL。这听起来似乎很简单对吧,但是并非我们想象的这样,很不幸由于这两个类型的特殊,JDBC并没有提供独立于数据库驱动的Blob和Clob建立对象。因此需要自己编写与驱动有关的代码,但这样又牵掣到移植性。怎样才是解决办法呢?这就要用到前面说过的思想了使用数据块进行写操作。同样用PreparedStatement和CallableStatememt类,但参数的设置可以换为setAsciiStream、setBinaryStream、setCharacterStream、setObject(当然前3个同样存在长度的问题)
下面给大家个例子以方便大家理解
public void insertFile(File f)  throws Exception{
FileInputStream fis=new FileInputStream(f,Connection conn);
byte[] buffer=new byte[1024];
data=null;
int sept=0;int len=0;

while((sept=fis.read(buffer))!=-1){
if(data==null){
len=sept;
data=buffer;
}else{
byte[] temp;
int tempLength;

tempLength=len+sept;
temp=new byte[tempLength];
System.arraycopy(data,0,temp,0,len);
System.arraycopy(buffer,0,temp,len,sept);
data=temp;
len=tempLength;
}
if(len!=data.length()){
byte temp=new byte[len];
System.arraycopy(data,0,temp,0,len);
data=temp;
}
}
String sql="insert into fileData (filename,blobData) value(?,?)";
PreparedStatement ps=conn.prepareStatement(sql);
ps.setString(1,f.getName());
ps.setObject(2,data);
ps.executeUpdate();

}

最后由于刚刚说过Clob类型读取字符的长度问题,这里再给大家一段代码,希望对你有帮助
public static String getClobString(ResultSet rs, int col) {
  try {
   Clob c=resultSet.getClob(2);
   Reader reader=c.getCharacterStream():
   if (reader == null) {
return null;
   }
   StringBuffer sb = new StringBuffer();
   char[] charbuf = new char[4096];
   for (int i = reader.read(charbuf); i > 0; i =reader.read(charbuf)) {
sb.append(charbuf, 0, i);
   }
   return sb.toString();
  } catch (Exception e) {
   return "";
  }
}

另外似乎前面还提到过LIKE检索的问题。LONGVARCHAR类型中不可以用LIKE查找(至少ORA中不可以使用,其他的数据库我没有试过),在ORA中我们可以使用这样一个函数dbms_lob.instr来代替LIKE来个例子吧

select docid,dat0 from text where dbms_lob.instr(dat0,'魏',1,1)>0

在text表中有两个字段docid用来放文档编号dat0为clob类型存放文章内容;这句话的意思就是检索第一条dat0中出现第一次"魏"字的数据。听起来这个检索的数据有点象google的“手气不错”

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值