Hibernate - Недостаточно памяти для вставки большого двоичного объекта - PullRequest
4 голосов
/ 07 марта 2012

В POJO у меня есть:

public void setBlob(InputStream in, Long l) {
        this.blob = Hibernate.getLobCreator(SessionFactoryHelper.sessionFactory.getCurrentSession()).createBlob(in, l);
}

Я сделал hibernate.jdbc.use_streams_for_binary true в конфиге, но действительно ли это что-то меняет?

при сохранении сущности, на session.flush () я получаю:

   org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl release
INFO: HHH000010: On release of batch it still contained JDBC statements
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space
Heap dump file created [46180174 bytes in 1.662 secs]
    at java.util.Arrays.copyOf(Arrays.java:2271)
    at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:113)
    at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:140)
    at org.hibernate.type.descriptor.java.DataHelper.extractBytes(DataHelper.java:171)
    at org.hibernate.type.descriptor.java.BlobTypeDescriptor.unwrap(BlobTypeDescriptor.java:121)
    at org.hibernate.type.descriptor.java.BlobTypeDescriptor.unwrap(BlobTypeDescriptor.java:45)
    at org.hibernate.type.descriptor.sql.BlobTypeDescriptor$4$1.doBind(BlobTypeDescriptor.java:105)
    at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:92)
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:305)
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:300)
    at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:57)
    at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2599)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2853)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3291)
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:275)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1127)

Hibernate 4.1. Почему hibernate разворачивает поток в bytea? Как я могу сделать Hibernate, чтобы использовать подготовленный оператор setBinaryStream? Очень нужна помощь в этом.

Ответы [ 2 ]

1 голос
/ 08 марта 2012

Я полагаю, что проблема в том, что ваш объект в памяти все еще имеет заполненный байтовый массив. Это отдельная проблема от того, используется ли поток для сохранения его в базе данных.

Я предлагаю обходной путь: не храните капли в POJO. Храните большой двоичный объект отдельно, либо в базе данных через прямой JDBC, либо на диске, а затем просто сохраняйте ссылку на большой двоичный объект в вашем POJO (либо первичный ключ базы данных, либо путь к файлу / имя файла).

Затем, когда вам понадобится блоб обратно, получите ссылку из POJO и используйте потоковые методы для ее возврата.

Это больше работы, чтобы получать / сохранять большие двоичные объекты каждый раз, когда вам нужно, но если большой размер слишком велик для памяти, у вас может не быть другого выбора.

0 голосов
/ 07 марта 2012

Я не знаю, почему это не работает и должно, но то, что я сделал, чтобы сохранить BLOB-объект в базе данных с помощью Hibernate:

в POJO сопоставлено с таблицей:

    private byte[] serializedDocx; // + getter and setter

в методе:

    ...
     SessionFactory mf = ...
     sess = mf.openSession();
     //open connection
     sess.beginTransaction();
    ...
      ByteArrayOutputStream docxBos = new ByteArrayOutputStream();
      [write to docxBos]
      someEntity.setDocx(docxBos.toByteArray());
      sess.save(someEntity);

в myEntity.hbm.xml

  <property name="serializedDocx" type="binary">
      <column name="serialized_docx" not-null="true"/>
    </property>

в MySQL:

CREATE TABLE IF NOT EXISTS `docx` (
  `serialized_docx` longblob NOT NULL, ...

НТН.

...