Hibernate version: 3.0.5. Annotations 3.0beta2
Full stack trace of any exception that occurs:
java.lang.ClassCastException: org.hibernate.lob.SerializableBlob
at oracle.jdbc.driver.OraclePreparedStatement.setBlob(OraclePreparedStatement.java:5909)
at org.hibernate.type.ByteArrayBlobType.nullSafeSet(ByteArrayBlobType.java:92)
at org.hibernate.type.CustomType.nullSafeSet(CustomType.java:141)
at org.hibernate.persister.entity.BasicEntityPersister.dehydrate(BasicEntityPersister.java:1617)
at org.hibernate.persister.entity.BasicEntityPersister.dehydrate(BasicEntityPersister.java:1594)
at org.hibernate.persister.entity.BasicEntityPersister.insert(BasicEntityPersister.java:1850)
at org.hibernate.persister.entity.BasicEntityPersister.insert(BasicEntityPersister.java:2200)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:46)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:239)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:223)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:136)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:730)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:324)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)
Name and version of the database you are using: Oracle 10.1.0.3 with the 10.1.0.4 ojdbc driver. We are using the thin driver, oracle.jdbc.OracleDriver with a URL that starts jdbc:oracle:thin:@ .
org.hibernate.type.ByteArrayBlobType is not compatible with updating or creating Blobs in Oracle, due to a problem with Oracle Blob handling. You can see the error in the stack trace above. Basically, you receive a class cast exception if you call setBlob on an OraclePreparedStatement with anything besides an OracleBlob.
I believe this problem can be fixed by borrowing a portion of the Blob handling from org.hibernate.type.BlobType. Specifically, switch to using an input stream to insert the blob if the dialect in use, Oracle in this case, requires it.
The following chunk of code from BlobType can be appropriated:
Code:
public void set(PreparedStatement st, Object value, int index, SessionImplementor session)
throws HibernateException, SQLException {
if (value==null) {
st.setNull(index, Types.BLOB);
}
else {
if (value instanceof SerializableBlob) {
value = ( (SerializableBlob) value ).getWrappedBlob();
}
final boolean useInputStream = session.getFactory().getDialect().useInputStreamToInsertBlob() &&
(value instanceof BlobImpl);
if ( useInputStream ) {
BlobImpl blob = (BlobImpl) value;
st.setBinaryStream( index, blob.getBinaryStream(), (int) blob.length() );
}
else {
st.setBlob(index, (Blob) value);
}
}
}
The current code in ByteArrayBlobType always calls st.setBlob( index, Hibernate.createBlob( toSet ) );
It looks like the ByteArrayBlobType would need access to a SessionImplementor to do this, but I assume that is feasible.
I tried using ByteArrayBlobType against Oracle 9i, and 10g, with versions 9 and 10 of the driver, using the oci client and the thick client, and while you end up with a different stack trace, the problem is always present.