spring+hibernate 处理oracle clob (编辑中)

这几天由于项目需要,处理oracle Clob类型的数据,由于使用的是hibernate,网络上找的文章有太多是讲的hibernate1.x时代的了,通常都是一个强制转化为oracle.sql.CLOB /BLOB,结果当然是不行,因为hibernate2,3封装了一层,返回的实际上是hibernate.SerializableClob...  ,还看了一些hibernate UserType的使用,但总有局限性,比如版本要求,服务器要求。。。  
        现总结对比如下几种操作方法 :
大的范围来讲有两种驱动:oci,thin方式,oci本身支持>4k字节的传输,处理相对比较方便,但是要求连接数据库的一端必须安装oracle客户端环境(配置本地NET服务名
url: jdbc:oracle:oci8:@oracle )

如果想传输大于4K字节的数据,请使用OCI驱动,用HIBERNATE如果不获得ORACLE的CLOB实现,无法传输超过4K字节的数据;

方法一。
Hibernate 映射文件:
              name="clob_content"
            type="java.sql.Clob"
            update="true"
            insert="true"
            column="content"
            not-null="false"/>
JAVABEAN:   private java.sql.Clob clob_content;
                          

DaoImp:

public void saveItem(Item item) {
 
 String str = item.getContent();
   
  item.setClob_content(Hibernate.createClob(str));//这里构造了该clob,并设置到object中去
  getHibernateTemplate().saveOrUpdate(item);
  getHibernateTemplate().flush();
 }

public Item getItem(Long itemId) {
  Item item = (Item) getHibernateTemplate().get(Item.class, itemId);
if(item!=null){
   java.sql.Clob clob = item.getClob_content();
   Strint tempStr = clob.getSubString(1, (int) clob.length());
   item.setContent(tempStr);
  }
  return item;
 }

方法二:使用hibernate的用户类型 (参考: http://www.hibernate.org/76.html)
  (1)Hibernate 映射文件:
              name="clob_content"
            type="StringClobType"
            column="content"  
         />   
 (2)javabean:     private String clob_content;

 (3)
/* StringClobType类源码*/
import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringReader;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.sql.Clob;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.usertype.*;
public class StringClobType implements UserType {
 public int[] sqlTypes() {
  return new int[] { Types.CLOB };
 }
 public Class returnedClass() {
  return String.class;
 }
 public boolean equals(Object x, Object y) {
  return (x == y) || (x != null && y != null && (x.equals(y)));
 }
 public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
  Reader reader = rs.getCharacterStream(names[0]);
  if (reader == null)
   return null;
  StringBuffer sb = new StringBuffer();
  try {
   char[] charbuf = new char[4096];
   for (int i = reader.read(charbuf); i > 0; i = reader.read(charbuf)) {
    sb.append(charbuf, 0, i);
   }
  } catch (IOException e) {
   throw new SQLException(e.getMessage());
  }
  return sb.toString();
 }
 public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
  if (value != null) {
   StringReader r = new StringReader((String) value);
   st.setCharacterStream(index, r, ((String) value).length());
  } else {
   st.setNull(index, sqlTypes()[0]);
  }
 }
 public Object deepCopy(Object value) {
  if (value == null)
   return null;
  return new String((String) value);
 }
 public boolean isMutable() {
  return false;
 }
 /*
  * @see org.hibernate.usertype.UserType#hashCode(java.lang.Object)
  */
 public int hashCode(Object arg0) throws HibernateException {
  // TODO 自动生成方法存根
  return 0;
 }
 /*
  * @see org.hibernate.usertype.UserType#disassemble(java.lang.Object)
  */
 public Serializable disassemble(Object arg0) throws HibernateException {
  // TODO 自动生成方法存根
  return null;
 }
 /*
  * @see org.hibernate.usertype.UserType#assemble(java.io.Serializable, java.lang.Object)
  */
 public Object assemble(Serializable arg0, Object arg1) throws HibernateException {
  // TODO 自动生成方法存根
  return null;
 }
 /*
  * @see org.hibernate.usertype.UserType#replace(java.lang.Object, java.lang.Object, java.lang.Object)
  */
 public Object replace(Object arg0, Object arg1, Object arg2) throws HibernateException {
  // TODO 自动生成方法存根
  return null;
 }
}

DaoImp:
与其他字段一样的处理,get/set就可以了

/* End: StringClobType类源码*/




注意:以上两种方法,在采用oracle thin方式连接的情况下 经我测试都不能传输超过4K字节
采用oci连接方式(jdbc:oracle:oci8:@orclsid) 则可以,但必须设置 hibernate的propertie
0 (注意此设置有可能导致旧的代码有批量更新的问题,我的解决办法是其他代码采用一个新的数据源)

/* 
oracle10g JDBC驱动可以处理clob 类型,直接采用String 就好了,但采用hiberbate ,我不知道如何设置他的 特性: SetBigStringTryClob  为  true

http://www.javaworld.com.tw/jute/post/view?bid=11&id=80295&sty=1&tpg=1&age=0 
(楼主说可以,但我测试没有成功) 

//oracle 官方说明及例子
http://www.oracle.com/technology/sample_code/tech/java/codesnippet/jdbc/lob/LobToSP.html

http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/htdocs/jdbc_10201.html

http://www.oracle.com/technology/sample_code/tech/java/codesnippet/jdbc/clob10g/handlingclobsinoraclejdbc10g.html
*/

你可能感兴趣的:(spring+hibernate 处理oracle clob (编辑中))