Hibernate 简单字节[]字段级别的JPA惰性

Hibernate 简单字节[]字段级别的JPA惰性,hibernate,jpa,nhibernate-mapping,lazy-loading,jpa-2.0,Hibernate,Jpa,Nhibernate Mapping,Lazy Loading,Jpa 2.0,不幸的是,下面的代码不起作用。始终检索图像 @Entity public Car implements Serializable { ... @Basic(fetch = FetchType.LAZY) //Neither with @Lob private byte[] image; ... } 设置:JPA 2.0/Hibernate 3.5/MySQL 5.5 我记得这是一个很久以前的问题(大约在2007年):即为什么字节数组被急切地获取,即使它们被声明为

不幸的是,下面的代码不起作用。始终检索图像

@Entity
public Car implements Serializable {
    ...
    @Basic(fetch = FetchType.LAZY) //Neither with @Lob
    private byte[] image;
    ...
}
设置:JPA 2.0/Hibernate 3.5/MySQL 5.5


我记得这是一个很久以前的问题(大约在2007年):即为什么字节数组被急切地获取,即使它们被声明为懒惰的。显然Hibernate的人还没有解决这个问题

以下是一些可行的替代方案:

首先,试着用
@Lob
注释你的字段,看看它是否如预期的那样工作

其次,用
java.sql.Blob
替换
byte[]
,它具有设置和获取实际字节数组的方便方法,因此不会进行大的重构,这实际上可以解决延迟加载问题:


请记住,当您指定JPA提供程序延迟获取数据时,它不需要延迟获取数据。这是一个提示,而不是要求

JPA规范2.0 11.1.6

急切策略是持久性提供程序运行时的一项要求,即必须急切地获取数据。延迟策略是对持久性提供程序运行时的一个提示,即数据应该延迟获取 当它第一次被访问时。这一实施被急切地允许 获取已指定惰性策略提示的数据。在里面 特别是,延迟抓取可能仅适用于基本映射 对其使用基于属性的访问


据我所知,只有当您具有@OneToMany关系时才可能进行延迟加载(除非您使用类编织)。至少EclipseLink是这样解释的,从java语言的角度来看,这是有意义的。 当你有

@OneToMany (fetch = FetchType.LAZY)
Collection<Employee> employees;
@OneToMany(fetch=FetchType.LAZY)
收集员工;

Collection是一个接口,因此JPA可以轻松地使用自己的Collections实现,当您开始迭代数据时,它会延迟加载数据。如果对象的字段类型为
byte[]
it value为null或包含所有数据,那么Java就是这样工作的。避免这种情况的唯一方法是使用类编织并创建看起来像字节数组的字节码,但在访问之前不包含任何数据。

本主题介绍了如何实现这一点的技巧:

我已经在Hibernate v.4.3.5和JPA v.1.5.0、PostgreSQL 9.3上检查过了。工作得很有魅力。 例如:


注意:如果您使用的是CGLib,请使用相同的方法实现net.sf.CGLib.transform.impl.InterceptFieldEnabled而不是FieldHandled。

谢谢Pedro!那么我迷路了吗?佩德罗,我真的认为这是一个Hibernate bug(这不是他们在JPA实现上做的第一个bug)。检查此问题:。guy Basicali与您有相同的问题,建议的解决方案是:在您的实体(无图像)和另一个仅包含字节[]的实体之间建立一对一映射,并建立该关联lazy@AndreiBodnarescu当然,这可能是一个Hibernate错误,但是您不能假设JPA提供程序将延迟加载您的数据。在我看来,如果您的逻辑依赖于这样的特性,那么它应该被很好地记录下来,因为您在更改JPA提供程序时可能会感到惊讶。同意,但我认为这里发生的更多是“hibernate不要因为bug而进行延迟加载”,而不是“hibernate不做延迟加载,因为它高度尊重JPA规范,JPA规范说这只是一个提示”。我认为如果你试图通过关联延迟加载它,hibernate实际上会进入“根据JPA规范延迟加载”“并且选择了实际的延迟加载。好吧,那么CellinHc,你能试试@AndreiBodnarescu建议的方式吗?”?您还可以检查从基于字段的访问转移到基于属性的访问是否会改变一件事。谢谢您,Andrei,但这些方法对我不起作用。大问题<代码>@Lob@Basic(fetch=FetchType.LAZY)Blob私有字节[]映像EntityManager无法保留此属性。。。保留所有字段,并且
image
保持为空。我使用的是具体的类
SerialBlob
似乎OP使用的是Hibernate而不是EclipseLink
public class Attachment implements FieldHandled{
    @Transient
    private FieldHandler fieldHandler;
...
...
    @Lob
    @Column(name=CONTENT, nullable=false)
    @Basic(fetch = FetchType.LAZY, optional = false)
    private byte[] content;

...
...
    public byte[] getContent() {
    if(fieldHandler!=null){
        return (byte[])fieldHandler.readObject(this, "content", content);
    }
    return content;
    }

    public void setContent(byte[] content) {
    if(fieldHandler!=null){
        fieldHandler.writeObject(this, "content", this.content, content);
        return;
    }
    this.content = content;
    }

}