简体   繁体   English

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

[英]Using JdbcTemplate to insert large CLOB's into Oracle fails

I am interfacing with an Oracle database via Spring's JdbcTemplate utility class, and I have tried these two variants of code: 我通过Spring的JdbcTemplate实用程序类与Oracle数据库连接,我尝试了这两种代码变体:

jdbcTemplate.update("INSERT INTO my_table (title, content) VALUES (?, ?)", title, content);

-- or -- - 要么 -

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;
    }
});

Where title is a traditional VARCHAR2 , and content is a CLOB . title是传统的VARCHAR2contentCLOB

Either of these alternatives work for smaller values for content . 这些替代方案中的任何一个都适用于较小的content值。 However, when I have larger amounts of content , nothing gets inserted into the CLOB column. 但是,当我有大量content ,没有任何content插入到CLOB列中。

Interestingly enough, in both cases, title gets updated. 有趣的是,在这两种情况下, title都会更新。 It's as if the query just ignores content if there's too much, but never throws an error. 就好像查询只是忽略content如果有太多,但从不抛出错误。

Does anybody know how I should solve this? 有谁知道我该怎么解决这个问题?

Thanks. 谢谢。

EDIT : 编辑

Per the answer from @GreyBeardedGeek, I tried using OracleLobHandler and DefaultLobHandler , to the same effect. 根据@GreyBeardedGeek的回答,我尝试使用OracleLobHandlerDefaultLobHandler ,效果相同。 Things work until my CLOB 's reach a certain size. 事情一直有效,直到我的CLOB达到一定的规模。

I also tried the following code, again to the same effect: 我也尝试了以下代码,同样效果:

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();

I'm baffled as to why every one of these methods would work for smaller CLOB 's, but then suddenly break for large ones. 令我感到困惑的是,为什么这些方法中的每一种都适用于较小的CLOB ,但随后突然间会破坏大型CLOB Is there some type of configuration in the DB that I'm missing? DB中是否存在某种类型的配置? Or is the problem with the code? 或者是代码的问题?

Okay, I feel pretty silly. 好的,我觉得很傻。 As it turns out, even this simple code was storing the CLOB correctly: 事实证明,即使是这个简单的代码也正确地存储了CLOB

jdbcTemplate.update("UPDATE my_table SET title = ?, content = ? WHERE id = ?", getTitle(), getContentString(), getId());

The issue was my code that retrieved the CLOB back from the database. 问题是我从数据库中检索CLOB代码。 The following is my speculation based on my code (and the fix): it seems as though smaller CLOB 's get cached in memory, and can be read at a later time (namely, after the connection is closed, they can still be read). 以下是基于我的代码(和修复)的推测:似乎较小的CLOB被缓存在内存中,并且可以在以后读取(即,在连接关闭后,它们仍然可以被读取)。 However, for larger CLOB 's, they must be read while the connection is still open. 但是,对于较大的CLOB ,必须在连接仍然打开时读取它们。

For me, this meant the fix was as simple as reading the CLOB 's contents as soon as it was available to my object. 对我来说,这意味着修复就像在我的对象可用时一样读取CLOB的内容一样简单。 In my case, I'm not really worried about memory issues, because I don't expect that my CLOB 's will contain inordinately sized contents, and so reading the value into memory immediately is an acceptable approach. 在我的情况下,我并不是真的担心内存问题,因为我不希望我的CLOB包含非常大的内容,因此立即将值读入内存是一种可接受的方法。

Oracle has, for as long as I can remember, required special handling for BLOBs and CLOBs. 在我记忆中,Oracle已经需要对BLOB和CLOB进行特殊处理。 Spring JDBC has org.springframework.jdbc.support.lob.OracleLobHandler for setting the value of BLOBs and CLOBs. Spring JDBC有org.springframework.jdbc.support.lob.OracleLobHandler,用于设置BLOB和CLOB的值。

There's a pretty good full example of how to use it at http://techdive.in/spring/spring-handling-blobclob but basically, instead of ps.setStringForClob , you would do http://techdive.in/spring/spring-handling-blobclob上有一个非常好的完整示例如何使用它,但基本上,你会做,而不是ps.setStringForClob

oracleLobHandler.getLobCreator().setClobAsString(ps, 2, content);

SqlLobValue(String content) can be used for CLOB. SqlLobValue(String content)可用于CLOB。

Follow the link: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/core/support/SqlLobValue.html 请点击以下链接: http//docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/core/support/SqlLobValue.html

.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM