<p> </p>
<p>前提:oracle中用一个clob字段。hbm.xml中对应的是java.sql.Clob/ </p>
<p>?</p>
<p>?</p>
<pre name="code" class="java"> <property
name="answer"
type="java.sql.Clob"
update="true"
insert="true"
column="answer"
/></pre>
<p>?</p>
<p>?</p>
<p>pojo中:</p>
<p>???? </p>
<pre name="code" class="java"> ....... 其他属性
private java.sql.Clob;
public Clob getAnswer() {
return this.answer;
}
public void setAnswer(Clob answer) {
this.answer = answer;
}
.........其他方法</pre>
<p>?</p>
<p>存储的时候用session.save(obj)的方法;</p>
<p>这样做 clob属性中数据少的时候没报错。但数据量大的时候就会抛莫名其妙的异常。</p>
<p>问题出在Oracce中Blob/Clob字段独特的访问方式,Oracle Blob/Clob字段本身拥有一个游标(cursor) , JDBC必须通过游标对Blob/ Clob字段进行操作,在Blob/Clob字段被创建之前,我们无法获取其游标句柄,这也就意味着,我们必须首先创建一个空Blob/Clob字段,再从这个空Blob/Clob字段获取游标,写入我们所期望保存的数据。</p>
<p>至于如何操作可参考本博客其他文章(转载的)。</p>
<p>?</p>
<p>这里主要讲述两个异常 </p>
<p>?</p>
<p>(1) java.lang.ClassCastException : org.hibernate.lob.clobImpl 转型异常</p>
<p>?? 原因:用hibernateTemplate.save(),或者session.save()保存完对象后发现其对象的类型是clobImpl的。</p>
<p>?? 此时强制转化就会报错。</p>
<p>???解决方法:要用session.refresh()方法。也就是说refresh()方法必须在取clob对象之前。</p>
<p>?(2) ORA-01002: 读取违反顺序</p>
<p>? 原因:在refresh方法的时候导致的</p>
<p>? 解决方法:用session开始一个事务。然后就最后末事务在提交。(至于为什么,我也不清楚)</p>
<p>?</p>
<p>上述主要涉及的是hibernate存储clob,若直接用jdbc同样注意两个错误。</p>
<p>(1)ORA-01002: 读取违反顺序</p>
<p>?同上原理。设置connection 自动提交为false,</p>
<p>???????????? ?? conn.setAutoCommit(false);</p>
<p>(2)ORA-22920: 未锁定含有 LOB 值的行</p>
<p>? 在select 时候 要加上 “for update ”</p>
<p>例子:</p>
<pre name="code" class="java">Connection conn = getConnection();
conn.setAutoCommit(false);
PreparedStatement p=conn.prepareStatement("select * from train_test where id='"+po.getId()+"' for update");
ResultSet rs = p.executeQuery();
rs.next();
CLOB testDesc= (CLOB) rs.getClob("test_desc");
CLOB answer= (CLOB) rs.getClob("answer");
testDesc.putString(1, getValue(ret,"试题题目"));
answer.putString(1, getValue(ret,"试题答案"));
p=conn.prepareStatement("update train_test set test_desc=? ,answer=?");
p.setClob(1, testDesc);
p.setClob(2, answer);
p.executeUpdate();
conn.commit();
</pre>