I thought I'd piggy back on this topic since I have the same problem - I have a Blob that the entire contents are getting read into memory so it throws OutOfMemory exception.
Hibernate version: 3.6.9
Java: 1.6.0_21
Oracle Database: 11.2.0.2.0
Oracle Drivers: 11.2.0.2.0
Hibernate config property:
Code:
<property name="hibernate.jdbc.use_streams_for_binary">true</property>
Here is my object's property mapping:
Code:
<property name="contents" column="CONTENTS" type="blob"/>
Java property:
Code:
private java.sql.Blob contents;
Creation code:
Code:
InputStream contents = ... // i'm getting these from a file
Blob b = Hibernate.createBlob(contents, contents.available())
Now when I save the Blob b, when there is a flush, it executes code that apparently is trying to convert the Blob into a byte[], so I get an OutOfMemoryError. Here:
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2786)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:94)
at org.hibernate.type.descriptor.java.DataHelper.extractBytes(DataHelper.java:170)
at org.hibernate.type.descriptor.java.BlobTypeDescriptor.unwrap(BlobTypeDescriptor.java:123)
at org.hibernate.type.descriptor.java.BlobTypeDescriptor.unwrap(BlobTypeDescriptor.java:47)
at org.hibernate.type.descriptor.sql.BlobTypeDescriptor$4$1.doBind(BlobTypeDescriptor.java:101)
at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:91)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:283)
at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:278)
at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:89)
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2184)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2430)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2874)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at uiowa.hawkirb.biz.AuditableHibernateSession.flush(AuditableHibernateSession.java:48)
at uiowa.hawkirb.biz.Persistent.save(Persistent.java:120)
at uiowa.hawkirb.site.attachment.ViewAttachmentsAction.createNewAttachment(ViewAttachmentsAction.java:522)
at uiowa.hawkirb.site.attachment.ViewAttachmentsAction.execute(ViewAttachmentsAction.java:198)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:425)
at uiowa.hawkirb.site.RequestProcessor.processActionPerform(RequestProcessor.java:41)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:228)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:462)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
Here is the method unwrap in BlobTypeDescriptor where the exception is getting thrown:
Code:
@SuppressWarnings({ "unchecked" })
public <X> X unwrap(Blob value, Class<X> type, WrapperOptions options) {
if ( ! ( Blob.class.isAssignableFrom( type ) || BinaryStream.class.isAssignableFrom( type ) ) ) {
throw unknownUnwrap( type );
}
if ( value == null ) {
return null;
}
if ( BinaryStream.class.isAssignableFrom( type ) ) {
try {
return (X) new BinaryStreamImpl( DataHelper.extractBytes( value.getBinaryStream() ) );
}
catch ( SQLException e ) {
throw new HibernateException( "Unable to access blob stream", e );
}
}
final Blob blob = WrappedBlob.class.isInstance( value )
? ( (WrappedBlob) value ).getWrappedBlob()
: value;
return (X) blob;
}
This is the line throwing the exception:
Code:
return (X) new BinaryStreamImpl( DataHelper.extractBytes( value.getBinaryStream() ) );
It is trying to change everything into a byte[], and then back into BinaryStreamImpl?
Is there a way I can somehow tell hibernate not to put everything into a byte[] like this?