我通过Spring的JdbcTemplate
实用程序类与Oracle数据库连接,我尝试了这两种代码变体:
jdbcTemplate.update("INSERT INTO my_table (title, content) VALUES (?, ?)", title, content);
- 或 -
jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
OraclePreparedStatement ps = (OraclePreparedStatement)conn.prepareStatement("INSERT INTO my_table (title, content) VALUES (?, ?)");
ps.setString(1, title);
ps.setStringForClob(2, content);
return ps;
}
});
其中title
是传统的VARCHAR2
,而content
是CLOB
。
这些替代方案中的任何一个都适用于content
的较小值。但是,当我的content
数量较大时,CLOB
列中不会插入任何内容。
有趣的是,在这两种情况下,title
都会得到更新。好像查询只是忽略content
,如果有太多,但从不抛出错误。
有人知道我应该如何解决这个问题吗?
感谢。
修改:
根据@GreyBeardedGeek的回答,我尝试使用OracleLobHandler
和DefaultLobHandler
,效果相同。在CLOB
达到一定规模之前,事情一直有效。
我也尝试了以下代码,同样效果:
Connection conn = db.getDataSource().getConnection();
CLOB clob = CLOB.createTemporary(conn, false, CLOB.DURATION_SESSION);
clob.setString(1, myString);
OraclePreparedStatement ps = (OraclePreparedStatement)conn.prepareStatement("UPDATE my_table SET blob = ?");
ps.setCLOB(1, clob);
ps.execute();
我感到困惑的是,为什么这些方法中的每一种都适用于较小的CLOB
,但随后突然中断大型的{{1}}。数据库中是否存在某些类型的配置?或者是代码的问题?
答案 0 :(得分:3)
好的,我觉得很傻。事实证明,即使这个简单的代码也正确地存储了CLOB
:
jdbcTemplate.update("UPDATE my_table SET title = ?, content = ? WHERE id = ?", getTitle(), getContentString(), getId());
问题是我的代码从数据库中检索到CLOB
。以下是基于我的代码(和修复)的推测:似乎较小的CLOB
被缓存在内存中,并且可以在以后读取(即,在连接之后关闭,他们仍然可以阅读)。但是,对于较大的CLOB
,必须在连接仍处于打开状态时读取它们。
对我来说,这意味着修复就像在我的对象可用时尽快阅读CLOB
的内容一样简单。在我的情况下,我并不是真的担心内存问题,因为我不希望我的CLOB
包含非常大的内容,所以立即将值读入内存是一种可以接受的方法。
答案 1 :(得分:0)
在我记忆中,Oracle已经需要对BLOB和CLOB进行特殊处理。 Spring JDBC有org.springframework.jdbc.support.lob.OracleLobHandler,用于设置BLOB和CLOB的值。
有一个非常好的完整示例,说明如何在http://techdive.in/spring/spring-handling-blobclob使用它,但基本上,而不是ps.setStringForClob
,你会做
oracleLobHandler.getLobCreator().setClobAsString(ps, 2, content);
答案 2 :(得分:-3)
SqlLobValue(String content)
可用于CLOB。