# Hibernate 6.6.x breaks Oracle Blob Streaming

**URL:** <https://discourse.hibernate.org/t/hibernate-6-6-x-breaks-oracle-blob-streaming/10881>\
**Category:** Hibernate ORM\
**Created:** [January 14, 2025, 1:48pm UTC](https://discourse.hibernate.org/t/hibernate-6-6-x-breaks-oracle-blob-streaming/10881 "2025-01-14T13:48:50Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![rascmatt](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/rascmatt/32/3765_2.png) [@rascmatt](https://discourse.hibernate.org/u/rascmatt)\
**Post date:** [January 14, 2025, 1:48pm UTC](https://discourse.hibernate.org/t/hibernate-6-6-x-breaks-oracle-blob-streaming/10881/1 "2025-01-14T13:48:50Z")

</div>

I’m having an issue with streaming large files to the oracle DB using Spring Boot and Hibernate.

This issue occurs after a Spring Boot Upgrade to 3.4.1 (from 3.2.5), which includes the new minor version Hibernate 6.6.4. I’m using oracle driver ojdbc8-21.3.0.0.

I have an entity definition like this

```auto
import java.sql.Blob;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Lob;

@Entity
public class Table
{

    @Lob
    @Column(name = "data")
    private Blob data;
    
}

```

In order to stream a large input file to the database I’m using `BlobProxy.generateProxy(in, length)` to set up the blob proxy with my input stream.

Upon transaction commit I now get the following exception:

```auto
Caused by: java.lang.ClassCastException: class org.hibernate.engine.jdbc.BlobProxy cannot be cast to class oracle.jdbc.internal.OracleBlob (org.hibernate.engine.jdbc.BlobProxy and oracle.jdbc.internal.OracleBlob are in unnamed module of loader 'app')
	at oracle.jdbc.driver.OraclePreparedStatement.setBlob(OraclePreparedStatement.java:6528)
	at oracle.jdbc.driver.OraclePreparedStatementWrapper.setBlob(OraclePreparedStatementWrapper.java:153)
	at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.setBlob(HikariProxyPreparedStatement.java)
	at org.hibernate.type.descriptor.jdbc.BlobJdbcType$4$1.doBind(BlobJdbcType.java:173)
	at org.hibernate.type.descriptor.jdbc.BlobJdbcType$2$1.doBind(BlobJdbcType.java:115)
	at org.hibernate.type.descriptor.jdbc.BasicBinder.bind(BasicBinder.java:61)
	at org.hibernate.engine.jdbc.mutation.internal.JdbcValueBindingsImpl.lambda$beforeStatement$0(JdbcValueBindingsImpl.java:87)
	at java.base/java.lang.Iterable.forEach(Iterable.java:75)
	at org.hibernate.engine.jdbc.mutation.spi.BindingGroup.forEachBinding(BindingGroup.java:51)
	at org.hibernate.engine.jdbc.mutation.internal.JdbcValueBindingsImpl.beforeStatement(JdbcValueBindingsImpl.java:85)
	at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.performNonBatchedMutation(AbstractMutationExecutor.java:130)
	at org.hibernate.engine.jdbc.mutation.internal.MutationExecutorSingleNonBatched.performNonBatchedOperations(MutationExecutorSingleNonBatched.java:55)
	at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.execute(AbstractMutationExecutor.java:55)
	at org.hibernate.persister.entity.mutation.InsertCoordinatorStandard.doStaticInserts(InsertCoordinatorStandard.java:194)
	at org.hibernate.persister.entity.mutation.InsertCoordinatorStandard.coordinateInsert(InsertCoordinatorStandard.java:132)
	at org.hibernate.persister.entity.mutation.InsertCoordinatorStandard.insert(InsertCoordinatorStandard.java:104)
	at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:110)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:644)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:511)
	at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:414)
	at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:41)
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127)
	at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1429)
	at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:491)
	at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2354)
	at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:1978)
	at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:439)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:169)
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:267)
	at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)

```

This seems to be related to [HHH-18206](https://hibernate.atlassian.net/browse/HHH-18206), and [HHH-18206 Switch to JDBC LOB APIs for Oracle Dialect by loiclefevre · Pull Request #8486 · hibernate/hibernate-orm · GitHub](https://github.com/hibernate/hibernate-orm/pull/8486), where the binding of the blog type changed from STREAM\_BINDING to BLOB\_BINDING in the org.hibernate.type.descriptor.jdbc.BlobJdbcType. While hibernate unwraps the blob to the java.sql.Blob type, the oracle driver seems to expect an instance of oracle.jdbc.internal.OracleBlob.

Is there an alternative ways to create a blob proxy now from an input stream? Or maybe an alternative way to stream large objects to the DB that works for oracle?

I’m happy to provide more details if necessary.

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [January 14, 2025, 3:47pm UTC](https://discourse.hibernate.org/t/hibernate-6-6-x-breaks-oracle-blob-streaming/10881/2 "2025-01-14T15:47:55Z")

</div>

Please try to create a reproducer with our [test case template](https://github.com/hibernate/hibernate-test-case-templates/blob/master/orm/hibernate-orm-6/src/test/java/org/hibernate/bugs/JPAUnitTestCase.java) and if you are able to reproduce the issue, create a bug ticket in our [issue tracker](https://hibernate.atlassian.net) and attach that reproducer.

---

<div class="post-metadata">

**Author:** ![rascmatt](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/rascmatt/32/3765_2.png) [@rascmatt](https://discourse.hibernate.org/u/rascmatt)\
**Post date:** [January 15, 2025, 3:10pm UTC](https://discourse.hibernate.org/t/hibernate-6-6-x-breaks-oracle-blob-streaming/10881/3 "2025-01-15T15:10:38Z")

</div>

@beikov

Thanks for the reference to the test case template, I forked it and was able to reproduce the issue in a simple test case. See [GitHub - rascmatt/hibernate-test-case-templates: Templates and examples to report issues to Hibernate](https://github.com/rascmatt/hibernate-test-case-templates)

Initially it worked fine, but the template helped me to narrow down the reproducing conditions. It seems that the exception occurs specifically when disabling the `hibernate.boot.allow_jdbc_metadata_access` configuration property.

I also noticed, that due to the changes in [HHH-18206 Switch to JDBC LOB APIs for Oracle Dialect by loiclefevre · Pull Request #8486 · hibernate/hibernate-orm · GitHub](https://github.com/hibernate/hibernate-orm/pull/8486) the stream-writing of the lobs was disabled generally for Lobs in Oracle. That is, even if run with `metadata_access` set to true, which does not produce this exception, internally the stream is first read to a byte array, and then wrapped in an Oracle blob proxy (See `org.hibernate.type.descriptor.java.BlobJavaType#getOrCreateBlob`).

So, before I open a bug ticket, I’d like to discuss if this is generally discouraged now, and if there’s an alternative way of streaming data into blobs in Hibernate, which does not load everything into memory.

I find the current API (using `BlobProxy.generateProxy(InputStream stream, long length)`) quite misleading, because it looks like its able to handle an input stream, and not load the whole file into memory internally.

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [January 16, 2025, 10:37am UTC](https://discourse.hibernate.org/t/hibernate-6-6-x-breaks-oracle-blob-streaming/10881/4 "2025-01-16T10:37:43Z")

</div>

> [@rascmatt](#):
>
> Initially it worked fine, but the template helped me to narrow down the reproducing conditions. It seems that the exception occurs specifically when disabling the `hibernate.boot.allow_jdbc_metadata_access` configuration property.

This is unfortunate. From what I can see, we would need to add a configuration option to `org.hibernate.cfg.JdbcSettings` to allow controlling this behavior when JDBC metadata access is disabled. Please create an improvement request for that on our issue tracker.

> [@rascmatt](#):
>
> I find the current API (using `BlobProxy.generateProxy(InputStream stream, long length)`) quite misleading, because it looks like its able to handle an input stream, and not load the whole file into memory internally.

You have a point. I agree that the `JdbcType` implementations should avoid materializing the full data when the passed value is based on a stream. It seems there even was [some experimentation done](https://github.com/hibernate/hibernate-orm/commit/f9e544e394ffb3106cd408373d3852454dd60140) on that matter, but wasn’t finished. Please also create an improvement request on our issue tracker for this.

---

<div class="post-metadata">

**Author:** ![swd\_eagle](https://avatars.discourse-cdn.com/v4/letter/s/f14d63/32.png) [@swd\_eagle](https://discourse.hibernate.org/u/swd_eagle)\
**Post date:** [February 24, 2025, 10:46am UTC](https://discourse.hibernate.org/t/hibernate-6-6-x-breaks-oracle-blob-streaming/10881/5 "2025-02-24T10:46:44Z")

</div>

We have the same issue. Is there a fix or workaround for this yet? Or when is it expected?

---

<div class="post-metadata">

**Author:** ![rascmatt](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/rascmatt/32/3765_2.png) [@rascmatt](https://discourse.hibernate.org/u/rascmatt)\
**Post date:** [February 24, 2025, 11:33am UTC](https://discourse.hibernate.org/t/hibernate-6-6-x-breaks-oracle-blob-streaming/10881/6 "2025-02-24T11:33:20Z")

</div>

@swd_eagle

Sorry, I did not follow up on this after having some troubles creating an account for the issue tracker and eventually choosing another route (moving away from blobs in the DB entirely) due to time pressure.

So, afaik there is currently noone working on this. But I can give it another shot and finally create some tickets for it. Or if you have resources available, you’re welcome to use my test case for the ticket.

Essentially there are two issues here:

- Make the blob binding configurable, so hibernate does not rely on the metadata access to be enabled
- Fix the blob (un-) wrapping to not read the whole stream into memory

---

<div class="post-metadata">

**Author:** ![swd\_eagle](https://avatars.discourse-cdn.com/v4/letter/s/f14d63/32.png) [@swd\_eagle](https://discourse.hibernate.org/u/swd_eagle)\
**Post date:** [February 24, 2025, 12:44pm UTC](https://discourse.hibernate.org/t/hibernate-6-6-x-breaks-oracle-blob-streaming/10881/7 "2025-02-24T12:44:10Z")

</div>

I don’t know enough about the internal workings to give the proper information, certainly not to the extent you did. Would be great if you could create a support ticket.

We tried to switch to byte instead of SerialBlob, but then all data in the database already saved as SerialBlob failed to load as byte. I hoped they were compatible, but apparently not.

---

<div class="post-metadata">

**Author:** ![rascmatt](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/rascmatt/32/3765_2.png) [@rascmatt](https://discourse.hibernate.org/u/rascmatt)\
**Post date:** [February 24, 2025, 3:31pm UTC](https://discourse.hibernate.org/t/hibernate-6-6-x-breaks-oracle-blob-streaming/10881/8 "2025-02-24T15:31:29Z")

</div>

I created two new issues:

- [HHH-19200](https://hibernate.atlassian.net/browse/HHH-19200) for making the lob streaming configurable
- [HHH-19201](https://hibernate.atlassian.net/browse/HHH-19201) for adapting the blob wrapping to not read the whole input stream into a byte array

However, I’m also far from a hibernate expert, so the descriptions in the tickets might not consider the whole picture. (E.g. I don’t quite understand the reasoning behind disabling the streaming support for oracle in the first place)

@swd_eagle  
I’m not sure if this is exactly your issue then, because I would have assumed that de-serializing to a byte array should work just fine. You’ll loose the streaming behavior, but other than that I don’t see why it shouldn’t work. Maybe there’s an encoding issue with your data?

---

<div class="post-metadata">

**Author:** ![swd\_eagle](https://avatars.discourse-cdn.com/v4/letter/s/f14d63/32.png) [@swd\_eagle](https://discourse.hibernate.org/u/swd_eagle)\
**Post date:** [June 20, 2025, 6:39am UTC](https://discourse.hibernate.org/t/hibernate-6-6-x-breaks-oracle-blob-streaming/10881/9 "2025-06-20T06:39:06Z")

</div>

@beikov - is there any update on this? The two issues that were created by the other posted?

This is blocking for us, we’re stuck on Hibernate 6.5.3 because of it.

---

<div class="post-metadata">

**Author:** ![beikov](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/beikov/32/258_2.png) [@beikov](https://discourse.hibernate.org/u/beikov)\
**Post date:** [June 20, 2025, 7:36am UTC](https://discourse.hibernate.org/t/hibernate-6-6-x-breaks-oracle-blob-streaming/10881/10 "2025-06-20T07:36:27Z")

</div>

There is no update as you can see on the issues. When we find the time, we will look into the reports.  
If you have pressing needs, please consider requesting a fix through Red Hat or IBM support. As you can imagine, the Hibernate team treats such requests with the highest priority, since the money for such support contracts is essentially what pays our salaries.  
When paying for support is no option, you will have to wait until we find the time to look into this or pay someone else to work on this if you can’t or don’t want to contribute yourself.
