簡體   English   中英

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

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

我將 JPA (Hibernate) 與 Spring 一起使用。 當我想延遲加載字符串屬性時,我使用以下語法:

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

Lazy Lob加載需要字節碼檢測才能正常工作,因此默認情況下它在我所知道的任何JPA實現中都不可用。

最好的辦法是將Lob放入一個單獨的實體,如HtmlSummary ,並使用一個懶惰加載的一對一關聯。

使用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;
    }
}

我使用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在一個事務性的,那么它會正常工作。

首先,您應該知道JPA規范明確規定LAZY只是對JPA提供商的暗示,因此它不是強制性要求。

要使基本類型的延遲抓取工作,您需要啟用字節碼增強並將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>

根據JPA的規范,他們說即使你使用注釋屬性來懶惰地獲取,也不能保證應用,因此屬性可能會或可能不會被懶惰地加載(取決於JPA的實現者),但是如果你指定你應該急切地獲取它們然后JPA實現者必須急切地加載它們。

底線:@Basic(fetch = FetchType.LAZY)可能有效,也可能無效,取決於JPA實現者。

我認為它類似於EclipseLink,你需要啟用編織,否則fetch設置不起作用。 編織需要字節碼訪問。 這可能會有所幫助: https//stackoverflow.com/a/18423704/7159396

我用@Lob<\/code>注釋了我的列,它的類型是byte[]<\/code> ,但它總是急切地加載。

我嘗試過了:

  • @Basic(fetch = FetchType.LAZY)<\/code>注釋它<\/li>
  • 設置hibernate.bytecode.use_reflection_optimizer=false<\/code><\/li><\/ul>

    但這些解決方案都沒有奏效。

    我最終使用Blob<\/code>而不是byte[]<\/code>

    這個會被延遲加載,如果您需要檢索它的值,請訪問此字段:

延遲提取僅適用於對其他實體或實體集合的引用。 它不適用於String或int之類的值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM