简体   繁体   English

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

[英]@Basic(fetch = FetchType.LAZY) does not work?

I use JPA (Hibernate) with Spring.我将 JPA (Hibernate) 与 Spring 一起使用。 When I want to lazy load a String property, i use this syntax:当我想延迟加载字符串属性时,我使用以下语法:

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

Lazy Lob loading would require bytecode instrumentation to work properly, so it is not available by default in any JPA implementation I'm aware of. Lazy Lob加载需要字节码检测才能正常工作,因此默认情况下它在我所知道的任何JPA实现中都不可用。

Your best bet is to put the Lob into a separate entity, like HtmlSummary , and use a lazily loaded one-to-one association. 最好的办法是将Lob放入一个单独的实体,如HtmlSummary ,并使用一个懒惰加载的一对一关联。

Use FieldHandled with @Basic(fetch=FetchType.LAZY) works: 使用FieldHandled和@Basic @Basic(fetch=FetchType.LAZY)有效:

public class myFile implements Serializable, FieldHandled
{

    private FieldHandler      fieldHandler;

    @Lob
    @Basic(fetch = FetchType.LAZY)
    @Column(name = "CONTENT")
    protected byte[]          content;
@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;
    }
}

I use Hibernate4 h2database.I am sure lazy loading can work fine by my code. 我使用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 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=? Hibernate: select user_.img as img3_0_ from User user_ where user_.uid=?

if use repository.save(User) to add a new User will be ok, but update a User will throw a exception 如果使用repository.save(User)添加新用户就可以,但更新用户将抛出异常

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

I suggest use repository.delete(userid) before repository.save in one transactional, then it will work fine. 我建议使用repository.delete(userid)之前repository.save在一个事务性的,那么它会正常工作。

First of all, you should know that the JPA specs clearly specifies that LAZY is only a hint to JPA providers, so it's not a mandatory requirement. 首先,您应该知道JPA规范明确规定LAZY只是对JPA提供商的暗示,因此它不是强制性要求。

For basic type lazy fetching to work, you need to enable bytecode enhancement and explicitly set the enableLazyInitialization configuration property to true : 要使基本类型的延迟抓取工作,您需要启用字节码增强并将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>

from the specification of JPA they say that even if you use annotate a property to be fetched lazily, this is not guaranteed to be applied, so the properties may or may not be loaded lazily (depends on the implementer of JPA), however if you specify that you should fetch them Eagerly then the JPA implementer must load them eagerly. 根据JPA的规范,他们说即使你使用注释属性来懒惰地获取,也不能保证应用,因此属性可能会或可能不会被懒惰地加载(取决于JPA的实现者),但是如果你指定你应该急切地获取它们然后JPA实现者必须急切地加载它们。

Bottom line: @Basic(fetch = FetchType.LAZY) may or may not work, depends on the JPA implementer. 底线:@Basic(fetch = FetchType.LAZY)可能有效,也可能无效,取决于JPA实现者。

I think that it would be similar to EclipseLink, there you need to have enabled weaving otherwise, the fetch setting takes no effect. 我认为它类似于EclipseLink,你需要启用编织,否则fetch设置不起作用。 The weaving requires bytecode access. 编织需要字节码访问。 This could help: https://stackoverflow.com/a/18423704/7159396 这可能会有所帮助: https//stackoverflow.com/a/18423704/7159396

I had my column annotated with @Lob<\/code> and its type was byte[]<\/code> but it was always eager loaded.我用@Lob<\/code>注释了我的列,它的类型是byte[]<\/code> ,但它总是急切地加载。

I tried to:我尝试过了:

  • annotate it with @Basic(fetch = FetchType.LAZY)<\/code>@Basic(fetch = FetchType.LAZY)<\/code>注释它<\/li>
  • set hibernate.bytecode.use_reflection_optimizer=false<\/code>设置hibernate.bytecode.use_reflection_optimizer=false<\/code><\/li><\/ul>

    But none of these solutions worked.但这些解决方案都没有奏效。

    I ended up with using Blob<\/code> instead of byte[]<\/code>我最终使用Blob<\/code>而不是byte[]<\/code>

     @Column(name = "BlobField", nullable = false) @Lob @Basic(fetch = FetchType.LAZY) private Blob blobField;<\/code><\/pre>

    This one gets lazily loaded and if you need to retrieve its value access this field:这个会被延迟加载,如果您需要检索它的值,请访问此字段:

     String value = IOUtils.toByteArray(entity.getBlobField().getBinaryStream());<\/code><\/pre>"

Lazy fetching only applies to references to other entities or collections of entities. 延迟提取仅适用于对其他实体或实体集合的引用。 It does not apply to values like String or int. 它不适用于String或int之类的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM