@Basic(fetch = FetchType.LAZY)不起作用?

问题描述 投票:16回答:7

我在Spring中使用JPA(Hibernate)。当我想延迟加载一个String属性时,我使用以下语法:

@Lob
@Basic(fetch = FetchType.LAZY)
public String getHtmlSummary() {
    return htmlSummary;
}

但是当我看到hibernate创建的sql时,似乎这个属性不是延迟加载的?我也在ANT脚本中使用这个类org.hibernate.tool.instrument.javassist.InstrumentTask来检测这个属性,但似乎它不起作用。

请帮我。

在Khosro。

java hibernate jpa orm lazy-loading
7个回答
5
投票

懒惰的Lob加载需要字节码检测才能正常工作,所以默认情况下它在我所知道的任何JPA实现中都不可用。

你最好的选择是将Lob放入一个单独的实体,比如HtmlSummary,并使用一个懒惰加载的一对一关联。


3
投票

使用FieldHandled与@Basic(fetch=FetchType.LAZY)工作:

public class myFile implements Serializable, FieldHandled
{

    private FieldHandler      fieldHandler;

    @Lob
    @Basic(fetch = FetchType.LAZY)
    @Column(name = "CONTENT")
    protected byte[]          content;

3
投票
@Entity
public class User implements FieldHandled {

    @Id
    private String uid;

    private String uname;

    private int age;

    @Lob
    @Basic(fetch = FetchType.LAZY)
    private byte[] img;

    private FieldHandler fieldHandler;

    public User() {
    }

    // getter() and setter() of uid, uname, age

    public byte[] getImg() {
        // if User user = new User() then fieldHandler is null
        // if User user = entityManager.find(User.class, "001") then fieldHandler is not null
       if(img != null) { 
           return img;
       }

       if (fieldHandler != null) { 
           return (byte[]) fieldHandler.readObject(this, "img", img);
       } else {
           return null;
       }  
    }

    public void setImg(byte[] img) {
        this.img = img;
    }

    public void setFieldHandler(FieldHandler fieldHandler) {
        this.fieldHandler = fieldHandler;
    }

    public FieldHandler getFieldHandler() {
        return fieldHandler;
    }
}

我使用Hibernate4 h2database。我确定延迟加载可以通过我的代码正常工作。

Hibernate:select user0_.uid as uid1_0_0_, user0_.age as age2_0_0_, user0_.uname as uname4_0_0_ from User user0_ where user0_.uid=?

Hibernate:select user_.img as img3_0_ from User user_ where user_.uid=?

如果使用repository.save(User)添加新用户就可以,但更新用户将抛出异常

java.lang.ClassCastException: org.hibernate.bytecode.instrumentation.spi.LazyPropertyInitializer$1 cannot be cast to java.sql.Blob

我建议在repository.delete(userid)之前使用repository.save进行一次交易,然后它会正常工作。


3
投票

首先,您应该知道JPA规范明确规定LAZY只是对JPA提供商的暗示,因此它不是强制性要求。

要使基本类型的延迟抓取工作,您需要enable bytecode enhancement并将enableLazyInitialization配置属性显式设置为true

<plugin>
    <groupId>org.hibernate.orm.tooling</groupId>
    <artifactId>hibernate-enhance-maven-plugin</artifactId>
    <version>${hibernate.version}</version>
    <executions>
        <execution>
            <configuration>
                <enableLazyInitialization>true</enableLazyInitialization>
            </configuration>
            <goals>
                <goal>enhance</goal>
            </goals>
        </execution>
    </executions>
</plugin>

1
投票

根据JPA的规范,他们说即使你使用注释属性来懒惰地获取,也不能保证应用,因此属性可能会或可能不会被懒惰地加载(取决于JPA的实现者),但是如果你指定你应该急切地获取它们然后JPA实现者必须急切地加载它们。

底线:@Basic(fetch = FetchType.LAZY)可能有效,也可能无效,取决于JPA实现者。


0
投票

我认为它类似于EclipseLink,你需要启用编织,否则fetch设置不起作用。编织需要字节码访问。这可能会有所帮助:https://stackoverflow.com/a/18423704/7159396


-3
投票

延迟提取仅适用于对其他实体或实体集合的引用。它不适用于String或int之类的值。

© www.soinside.com 2019 - 2024. All rights reserved.