使用JdbcTemplate将大型CLOB插入Oracle失败

时间:2014-03-19 21:56:15

标签: java oracle spring-jdbc jdbctemplate clob

我通过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,而contentCLOB

这些替代方案中的任何一个都适用于content的较小值。但是,当我的content数量较大时,CLOB列中不会插入任何内容。

有趣的是,在这两种情况下,title都会得到更新。好像查询只是忽略content,如果有太多,但从不抛出错误。

有人知道我应该如何解决这个问题吗?

感谢。

修改

根据@GreyBeardedGeek的回答,我尝试使用OracleLobHandlerDefaultLobHandler,效果相同。在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}}。数据库中是否存在某些类型的配置?或者是代码的问题?

3 个答案:

答案 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)