【问题标题】:Read/write blob data in chunks with Hibernate使用 Hibernate 以块的形式读取/写入 blob 数据
【发布时间】:2014-01-04 01:59:30
【问题描述】:

有没有一种方法可以使用Hibernate 以块的形式读取和写入blob。 现在我得到了OutOfmemoryException,因为整个 blob 数据在内存中加载到了byte[]。

更具体地说,假设我想将一个大文件保存到一个名为 File 的数据库表中。

public class File {
   private byte[] data;
}

我在 FileInputStream 中打开文件,然后呢? 如何告诉 Hibernate 我需要流式传输内容并且不会一次提供整个 byte[] 数组? 我应该使用Blob 而不是byte[] 吗?无论如何,我怎样才能流式传输内容?

关于阅读,有没有一种方法可以告诉 hibernate(除了延迟加载之外)我需要以块的形式加载 blob,所以当我检索我的File 时,它不应该给我OutOfMemoryException。

我正在使用:

  • Oracle 11.2.0.3.0
  • 休眠 4.2.3 最终版
  • Oracle 驱动程序 11.2

【问题讨论】:

    标签: java oracle hibernate stream blob


    【解决方案1】:

    如果走 Blob 路线,您是否尝试过使用 Hibernate 的 LobHelper createBlob 方法,该方法采用 InputStream?要创建 Blob 并持久保存到数据库,您需要提供 FileInputStream 对象和字节数。

    您的文件 bean/实体类可以像这样映射 Blob(使用 JPA 注释):

    @Lob
    @Column(name = "DATA")
    private Blob data;
    
    // Getter and setter
    

    业务逻辑/数据访问类可以像这样为您的 bean/实体对象创建 Blob,注意不要在持久化到数据库之前关闭输入流:

    FileInputStream fis = new FileInputStream(file);
    Blob data = getSession().getLobHelper().createBlob(fis, file.length());
    fileEntity.setData(data);
    // Persist file entity object to database
    

    如果想以另一种方式从数据库中读取 Blob 作为块中的流,您可以调用 Blob 的 getBinaryStream 方法,为您提供 InputStream 并允许您稍后在需要时设置缓冲区大小:

    InputStream is = fileEntity.getData().getBinaryStream();
    

    Struts 2 has a convenient configuration available that can set the InputStream result's buffer size.

    【讨论】:

    • 如何在 hbm.xml 中定义@Lob(我们在 hbm.xml 文件中定义域对象)?
    • 我相信 @Lob 注释是可选的,只要你声明它是 type="blob"
    • 谁将关闭该流?
    • 我 相信 插入完成后,Hibernate 会关闭 Blob 的流。 Hibernate 使用其内部的BlobProxy 类。如果您调试并单步执行代码,您可以观察到代理 blob 的输入流最终会获得 true 的关闭值(在插入完成后立即)。但是在刷新会话后自己关闭流可能是个好习惯/transaction 已完成,因为它没有在 LobHelper 接口的合约中定义。
    • @RoySix 你知道 Blob 对象中是否包含所有内容并流回客户端代码还是从数据库中流式传输?
    猜你喜欢
    • 2011-03-31
    • 2012-08-18
    • 2014-07-23
    • 2023-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-20
    • 2018-04-06
    相关资源
    最近更新 更多