I am interfacing with an Oracle database via Spring's JdbcTemplate
utility class, and I have tried these two variants of code:
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
.
Either of these alternatives work for smaller values for content
. However, when I have larger amounts of content
, nothing gets inserted into the CLOB
column.
Interestingly enough, in both cases, title
gets updated. It's as if the query just ignores content
if there's too much, but never throws an error.
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. Things work until my CLOB
's reach a certain size.
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. Is there some type of configuration in the DB that I'm missing? 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:
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. 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). However, for larger CLOB
's, they must be read while the connection is still open.
For me, this meant the fix was as simple as reading the CLOB
's contents as soon as it was available to my object. 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.