Get stream from java.sql.Blob in Hibernate

I am trying to use hibernate @Entity with java.sql.Blob to store binary data. Storage does not raise any exceptions (however, I'm not sure if it really stores bytes), but reading does. Here is my test:

@Test
public void shouldStoreBlob() {
    InputStream readFile = getClass().getResourceAsStream("myfile");

    Blob blob = dao.createBlob(readFile, readFile.available());
    Ent ent = new Ent();
    ent.setBlob(blob);

    em.persist(ent);
    long id = ent.getId();

    Ent fromDb = em.find(Ent.class, id);

    //Exception is thrown from getBinaryStream()
    byte[] fromDbBytes = IOUtils.toByteArray(fromDb.getBlob().getBinaryStream());
}

Therefore, it throws an exception:

java.sql.SQLException: could not reset reader
    at org.hibernate.engine.jdbc.BlobProxy.getStream(BlobProxy.java:86)
    at org.hibernate.engine.jdbc.BlobProxy.invoke(BlobProxy.java:108)
    at $Proxy81.getBinaryStream(Unknown Source)
    ...

Why? Shouldn't he read bytes from the database here? And what can I do for this?

+3
source share
5 answers

Try updating the object:

em.refresh(fromDb);

The stream will be reopened. I suspect find (...) closes the blob stream.

+5
source

It's not entirely clear how you use JPA here, but of course you don't need to deal with the Blob data type directly if you use JPA.

@Lob :

@Lob
@Basic(fetch = LAZY)
@Column(name = "image")
private byte[] image;

, , , , .

, getter setter . :

private Image getImage() {
    Image result = null;

    if (this.image != null && this.image.length > 0) {
        result = new ImageIcon(this.image).getImage();
    }

    return result;
}

:

private void setImage(Image source) {

   BufferedImage buffered = new BufferedImage(source.getWidth(null), source.getHeight(null), BufferedImage.TYPE_INT_RGB);
   Graphics2D g = buffered.createGraphics();
   g.drawImage(source, 0, 0, null);
   g.dispose();

   ByteArrayOutputStream stream = new ByteArrayOutputStream();
   try {
      ImageIO.write(buffered, "JPEG", stream);
      this.image = stream.toByteArray();
    }
    catch (IOException e) {
      assert (false); // should never happen
    }
}

}

+2

org.hibernate.engine.jdbc.BlobProxy # getStream stream.reset() IOException:

    private InputStream getStream() throws SQLException {
            try {
                    if (needsReset) {
                            stream.reset(); // <---- Set breakpoint here
                    }
            }
            catch ( IOException ioe) {
                    throw new SQLException("could not reset reader");
            }
            needsReset = true;
            return stream;
    }

IOException org.apache.commons.io.input.AutoCloseInputStream Blob:

InputStream content = new AutoCloseInputStream(stream);
...
Ent ent = new Ent();
...
Blob blob = Hibernate.getLobCreator(getSession()).createBlob(content, file.getFileSize())
ent.setBlob(blob);
em.persist(ent);

Inpustream (, , org.postgresql.jdbc2.AbstractJdbc2Statement # setBlob Inpustream ). AutoCloseInputStream - IOException reset()

FileInputStream - reset. . blob . Ent, jdbc Postgres InputStream, . Ent (em.find(Ent.class, id)), BlobProxy, InputStream.

:

TransactionTemplate tt;

@Test
public void shouldStoreBlob() {
    final long id = tt.execute(new TransactionCallback<long>()
    {
        @Override
        public long doInTransaction(TransactionStatus status)
        {
            try
            {
                InputStream readFile = getClass().getResourceAsStream("myfile");

                Blob blob = dao.createBlob(readFile, readFile.available());
                Ent ent = new Ent();
                ent.setBlob(blob);

                em.persist(ent);
                return ent.getId();
            }
            catch (Exception e)
            {
                return 0;
            }
        }
    });

    byte[] fromStorage = tt.execute(new TransactionCallback<byte[]>()
    {
        @Override
        public byte[] doInTransaction(TransactionStatus status)
        {
            Ent fromDb = em.find(Ent.class, id);
            try
            {
                return IOUtils.toByteArray(fromDb.getBlob().getBinaryStream());
            }
            catch (IOException e)
            {
                return new byte[] {};
            }
        }
    });
}
+1

Hibernate, . . , . inputStream.close(), .

Another way: I tried calling free()the blob method method after the call session.save(attachment), but it throws another exception:

Exception in thread "main" java.lang.AbstractMethodError: org.hibernate.lob.SerializableBlob.free()V
 at my.hibernatetest.HibernateTestBLOB.storeStreamInDatabase(HibernateTestBLOB.java:142)
 at my.hibernatetest.HibernateTestBLOB.main(HibernateTestBLOB.java:60)

I use PostgreSQL 8.4 + postgresql-8.4-702.jdbc4.jar, Hibernate 3.3.1.GA

0
source

Is the IOUtils.toByteArray method closing the input stream?

-1
source

Source: https://habr.com/ru/post/1793068/


All Articles