[英]@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.