Oracle CLOB / BLOB & Spring

Reading and writing CLOBs and BLOBs from/to Oracle database via Spring’s JdbcTemplate might be a little bit confusing as it significantly differs from dealing with other types. Interested? Read on… :-)

Reading BLOB from database

This is relatively simple. Just use ResultSet.getBlob() or ResultSet.getClob() method (usually in our custom Spring’s RowMapper implementation) and read data using getBinaryStream() (for BLOBs) or getCharacterStream() (for CLOBs).

Inserting BLOB (CLOB) to database

Inserting must be done in two steps. First, we insert an empty BLOB (CLOB) into table row (along with other columns). Second, we lock & select currently inserted row from the table, open the stream and write data.

It is good to do both steps in one transaction (e.g. to prevent somebody from seeing empty BLOB in the meantime – but be sure to take transaction isolation level into account – READ COMMITTED or higher level is needed).

Let’s say we declare jdbcTemplate bean in our spring.xml:

[xml]





[/xml]

where dataSource is (got from JNDI):

[xml]
some/jndi/name
[/xml]

Running both steps of BLOB (CLOB) insertion code in transaction can be done like this:

[java]
byte[] data = new byte[] { … };
TransactionTemplate txTemplate = new TransactionTemplate(transactionManager);
MyTransaction transaction = new MyTransaction(data);
try {
txTemplate.execute(transaction);
//there might be something like: return transaction.getResult();
} catch (Exception e) {
//error… handle with care 😉
}
[/java]

Where MyTransaction for inserting BLOB could be (Java 1.4 this time):
[java]
private class MyTransaction extends TransactionCallbackWithoutResult {
private byte[] blobData;

public InsertPacketTransaction(byte[] blobData) {
this.blobData = blobData;
}

public void doInTransactionWithoutResult(TransactionStatus status) {
String sql = “insert into MYTABLE (MYID, …, MYBLOB) values (?, …, ?)”;

Integer myId = 0; //obtain ID for new record
BLOB blob = null;

try {
blob = BLOB.empty_lob();
} catch (SQLException e) {
//probably shouldn’t happen
}

int types[] = new int[] { Types.INTEGER, …, Types.BLOB };
Object args []= new Object[] { myId , …, blob };

jdbcTemplate.update(sql, args, types);

List packetList = jdbcTemplate.query(
“select MYBLOB from MYTABLE where MYID = ? FOR UPDATE”,
new Object[]{ myId },
new int[] { Types.INTEGER },
new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getBlob(“MYBLOB”);
}
}
);

if (packetList.size() == 1) {
OutputStream os;
try {
os = ((BLOB)packetList.get(0)).getBinaryOutputStream();
os.write(blobData);
os.flush();
os.close();
} catch (SQLException e) {
//handle
} catch (IOException e) {
//handle
}
} else {
//handle – this shouldn’t happen
}
}
}
[/java]

Writing CLOB is very similar – just use oracle.sql.CLOB instead of oracle.sql.BLOB everywhere and write data to CLOB using getCharacterOutputStream() method.

Tags: , , , , ,

3 Responses to “Oracle CLOB / BLOB & Spring”

  1. Lukas Barton says:

    Why don’t you use native Oracle blob manipulations? (i.e. oracle.sql.BLOB) The code would be shorter and without arbitrary select.

  2. ludek says:

    Hi, I would like to see such code, can you please provide an example?