发新话题
移动帖子 加入精华 加入置顶 加入收藏 关注此帖

Oracle Blob mapped to byte[] in Hibernate



Oracle Blob mapped to byte[] in Hibernate

Oracle Blob mapped to byte[] in Hibernate

I refer to Oracle 9i and Hibernate 2.1 to 3.0.5.

As found in the Hibernate forum, there is a problem of mapping a byte[] JavaBean property to "binary" in the Hibernate mapping file. Basically the byte array can be written to Oracle, but what's read back from Oracle is always 86 bytes which is the Oracle Blob locator itself!

Here is one solution I've found to get around this problem, assuming, say, the byte[] property name is "image",

1. Keep an internal member field for the byte[] image, with the standard {get|set}Image methods;

2. Add a pair of {get|set}ImageBlob methods for getting and setting the Blob datatype, without the repsective Blob member field. This pair of methods are intended to be invoked only by Hibernate;

3. Change the property mapping from "image" to "imageBlob", and use "blob" instead of "binary" for the type in the Hibernate mapping file.
Now the blob can be written to and read back from Oracle as byte[] as expected.

Note, with this approach, you may need to use the Oracle 10.1.0.4+ JDBC thin driver regardless to get around a problem related to the blob size greater than 2K bytes (even if you are running the Oracle 9.2.0.x database). Apparently it's related to a bug in the 9.2.0.x JDBC driver.

Example:


 
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.sql.Blob;
import java.sql.SQLException;
import org.hibernate.Hibernate;
public class TestHibernateBlob implements Serializable {
  byte[] image;
  public byte[] getImage() {
    return image;
  }
  public void setImage(byte[] image) {
    this.image = image;
  }
  /** Don't invoke this. Used by Hibernate only. */
  public void setImageBlob(Blob imageBlob) {
    this.image = this.toByteArray(imageBlob);
  }
  /** Don't invoke this. Used by Hibernate only. */
  public Blob getImageBlob() {
    return Hibernate.createBlob(this.image);
  }
  private byte[] toByteArray(Blob fromBlob) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
      return toByteArrayImpl(fromBlob, baos);
    } catch (SQLException e) {
      throw new RuntimeException(e);
    } catch (IOException e) {
      throw new RuntimeException(e);
    } finally {
      if (baos != null) {
        try {
          baos.close();
        } catch (IOException ex) {}
      }
    }
  }
  private byte[] toByteArrayImpl(Blob fromBlob, ByteArrayOutputStream baos) throws SQLException, IOException {
    byte[] buf = new byte[4000];
    InputStream is = fromBlob.getBinaryStream();
    try {
      for (;;) {
        int dataSize = is.read(buf);
        if (dataSize == -1)
          break;
        baos.write(buf, 0, dataSize);
      }
    } finally {
      if (is != null) {
        try {
          is.close();
        } catch (IOException ex) {}
      }
    }
    return baos.toByteArray();
  }
}

快乐渡过每一天,减肥坚持每一天
编辑 回复 快速回复 TOP

Re:Oracle Blob mapped to byte[] in Hibernate

编辑 回复 快速回复 TOP
发新话题