开发者

Hibernate throws SQLException Could not reset reader

java.sql.SQLException: could not reset reader
        at org.hibernate.lob.ClobImpl.getCharacterStream(ClobImpl.java:100)
        at org.hibernate.type.ClobType.set(ClobType.java:70)
        at org.hibernate.type.ClobType.nullSafeSet(ClobType.java:141)
        at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2025)
        at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2271)
        at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2688)
        at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)
        at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
        at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
        at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
        at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)

Hi,

Above is the stack trace. It is working with small amount of d开发者_Python百科ata but fails with large data. I cant figure out what could be the problem?

Regards, Preet


We just solved a similar problem and I would like to describe the problem here in case someone encounters it. Note that there is another question about the same problem. We have Oracle 10, Hibernate 3, Java 1.4 and patched Ojdbc14. We created CLOBs using ˇHibernate.createClob(String)ˇ. The program (batch job) failed on large strings (~700KB).

The problem was that with Hibernate we first inserted the entity with CLOB and the updated it (including CLOB). The second update was a part of many-to-one update. The CLOB didn't change in between, it's just that Hibernate wanted to update it twice. And it got this "could not reset" reader error. It seems that it can not use the same stream twice. We fixed this by making sure that CLOB is saved only once.


We had this issue when porting a MySQL-backed transaction system to a H2 database. (Somewhat similar to this issue on the now-obsolete Hibernate forums.)

Our story

  1. We had model entities with blob fields.
  2. In code, we were fetching batches of these entities transactionally, updating their status to "processing", and then reading the blob payloads outside the transaction (after the status update is committed) for the actual processing.
  3. Lazy-loading was not working initially, so every fetch was pulling in the blob field content along with the entity.

At transaction commit, Hibernate checks the dirtiness of each field, and pushes updates for all dirty fields back to the DB.

In Hibernate's change detection mechanism, blobs were always being treated as dirty (probably because you cannot compare two blobs in a non-invasive way; e.g. if one blob is stream-backed, you would have to actually consume the stream in order to compare its content with another blob).

Check out:

  • org.hibernate.type.AbstractStandardBasicType#isDirty(java.lang.Object, java.lang.Object, boolean[], org.hibernate.engine.spi.SharedSessionContractImplementor) and
  • org.hibernate.type.descriptor.java.BlobTypeDescriptor#areEqual

to see how blob comparison eventually boils down to a simple == check.

While you might expect this to still return true (as we never touch the blob field), proxy-wrapping and other Hibernate-level internals would cause the final blob object to be a different object altogether, failing the == test.

As a result...

  1. In the commit phase, every previously fetched blob was being consumed (read), in order for its content to be written back to the database.

This is not a problem for MySQL because their blobs are in-memory (and can be read multiple times without causing stream exhaustion). However H2 provides stream-backed blobs, which means they are read-once.

  1. So, when we were trying to (re-)read the blob after the transaction, Hibernate was trying to reset the already-consumed stream for the next read, and failing.

Our solution

The solution was simply to enable lazy loading for blob fields as outlined in this SO answer.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜