使用 Hibernate 和 Spring 创建 Blob

Posted

技术标签:

【中文标题】使用 Hibernate 和 Spring 创建 Blob【英文标题】:Blob creation using Hibernate and Spring 【发布时间】:2016-01-13 12:09:03 【问题描述】:

我正在使用 Spring 4.2.3、Hibernate 5.0.4、JPA 2.1 来进行 ORM 的自我训练。今天我正在学习如何在 Oracle 11.2.0.4 DB 中存储Blob。

在我的应用程序中,我有 Service 和 Dao 层。

问题: 为什么我应该使用需要当前会​​话的Hibernate.getLobCreator 创建Blob 实例?为什么不能再使用 [Hibernate.createBlob][3] (不访问当前会话)?

在某些情况下,我可能需要初始化 Blob 字段的瞬态域模型,而无需使用 Dao 将其持久化到数据库中。

是因为(如BlobJavaDoc 中所写):

Blob 对象在创建的事务期间有效。

很抱歉问了这么愚蠢的问题,但我找不到满意的答案。

[3]:https://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/Hibernate.html#createBlob(java.io.InputStream,长)

【问题讨论】:

或者更重要的是,当其他 JPA 提供者不需要时,为什么有必要使用供应商特定的方法来持久化 Blob? 为什么要手动创建 blob?为此,有@Lob 注释...只需将其添加到byte[]String 参数即可。不要自己乱搞(B / C)Lobs(很久以前就是这样做的)。 @M.Deinum 谢谢你的回答。您的意思是应该在映射中使用 byte[] 或 String 而不是 (B/C)Lobs 吗?但是在Hibernate 5.0 Lobs Documentation java.sql.Clob 中也使用了字段。 将为您完成映射。您真的希望您的实体依赖于 sql 特定类型吗?这基本上将您的整个应用程序与 sql 联系起来。但是 @Lob 注释也适用于 BlobClob 字段,但你真的想要这样吗,因为它使编写这些东西变得更加复杂。 我想到的另一件事:在我的模型与 Java 字符串池中将 (B/C)Lob 映射为 String 不是问题 - 这不是一些原因JVM内存问题? 【参考方案1】:

因为 Hibernate.createBlob 现在由于某些增强功能已从休眠中删除(我不记得确切的 jira 问题 :)。你可以在网上找到)。

所以你可以使用新的 Hibernate.getLobCreator,如下所示:

public Blob createBlob(your param) 
    return Hibernate.getLobCreator(currentSession()).createBlob();

// check different method for createBlob as you want to pass params.
// currentSession is method of HibernateDaoSupport 
// pass your session object instead of above

这里的 Blob 是 java.sql.Blob 的类型。不同类的其他 blob 方法正在实现此接口。因此,无论您使用 oracle 或 sql server 还是其他任何东西,您都将获得正确的 Blob....

因此,如果您使用的是 Hibernate 5.x.x,请按上述方式使用。

【讨论】:

如果您使用任何最新版本的 Hibernate,请使用带有 @Lob 注释的字段。 在 5.5.7 上,在尝试 Hibernate.getLobCreator(session) 时遇到了一些问题(来自 Hibernate 内部代码的类转换异常!)(已经使用了很长时间);所以改用session.getLobHelper().createBlob..【参考方案2】:

好的,我找到了一些关于如何在不访问会话对象的情况下初始化 Blob 的软解决方案。

我使用了SerialBlob 实现。下面是简单的源代码示例:

private Blob getBlob(String classpathLocation) 
    ClassPathResource imageFile = new ClassPathResource(classpathLocation);

    Blob resource = null;
    if (imageFile.exists()) 

        try 
            try (InputStream inputStream = imageFile.getInputStream()) 
                resource = new SerialBlob(StreamUtils.copyToByteArray(inputStream));
                LOG.warn("Resource loaded from ", classpathLocation);
            
         catch (Exception e) 
            LOG.error(MessageFormat.format("Unable to load resource from 0", classpathLocation), e);
        
     else 
        LOG.warn("Resource do not exist on ", classpathLocation);
    
    return resource;

【讨论】:

以上是关于使用 Hibernate 和 Spring 创建 Blob的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate 和 Spring:尝试创建事务时出现异常

java - 如何在java桌面应用程序中使用spring(事务)和hibernate创建嵌入式H2 DB?

当实体自引用时,Spring Boot 和 Hibernate 无法自动创建表

如果不存在,则通过将 spring Jpa 与 hibernate 一起使用来创建模式

请解释spring MVC,hibernate和Spring security

使用 JPA 和 Spring 加载选定的 Hibernate 实体