Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

Oracle has, for as long as I can remember, required special handling for BLOBs and CLOBs. Spring JDBC has org.springframework.jdbc.support.lob.OracleLobHandler for setting the value of BLOBs and CLOBs.

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

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top