Java @Basic(fetch = FetchType.LAZY) 不起作用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2112508/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
@Basic(fetch = FetchType.LAZY) does not work?
提问by Khosro
I use JPA (Hibernate) with Spring. When i want to lazy load a Stirng property i use this syntax:
我在 Spring 中使用 JPA(休眠)。当我想延迟加载一个 Stirng 属性时,我使用以下语法:
@Lob
@Basic(fetch = FetchType.LAZY)
public String getHtmlSummary() {
return htmlSummary;
}
But when i look at the sql that hibernate creates, it seems this property is not lazy loaded? I also use this class org.hibernate.tool.instrument.javassist.InstrumentTask in ANT script to instrument this property but it seems it does not work.
但是当我查看 hibernate 创建的 sql 时,似乎这个属性不是延迟加载的?我也在 ANT 脚本中使用这个类 org.hibernate.tool.instrument.javassist.InstrumentTask 来检测这个属性,但它似乎不起作用。
Please help me.
请帮我。
Khosro.
科斯罗。
回答by Mark Thornton
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 等值。
回答by Omar Al Kababji
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 实施者。
回答by Henning
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.
延迟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
,并使用延迟加载的一对一关联。
回答by William
Use FieldHandled with @Basic(fetch=FetchType.LAZY)
works:
将 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;
回答by lionyu
@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=?
休眠: 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=?
休眠: 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
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
,然后它会正常工作。
回答by Vlad Mihalcea
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 enhancementand 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>
回答by Petr Pahorecky
I think that it would be similar to EclipseLink, there you need to have enabled weaving otherwise, the fetch setting takes no effect. The weaving requires bytecode access. This could help: https://stackoverflow.com/a/18423704/7159396
我认为它与 EclipseLink 类似,否则您需要启用编织,否则 fetch 设置无效。编织需要字节码访问。这可能会有所帮助:https: //stackoverflow.com/a/18423704/7159396