Reputation: 1
I use JPA (Hibernate) with Spring. When I want to lazy load a String property, i use this syntax:
@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.
Upvotes: 30
Views: 35931
Reputation: 9469
I had my column annotated with @Lob
and its type was byte[]
but it was always eager loaded.
I tried to:
@Basic(fetch = FetchType.LAZY)
hibernate.bytecode.use_reflection_optimizer=false
But none of these solutions worked.
I ended up with using Blob
instead of byte[]
@Column(name = "BlobField", nullable = false)
@Lob
@Basic(fetch = FetchType.LAZY)
private Blob blobField;
This one gets lazily loaded and if you need to retrieve its value access this field:
String value = IOUtils.toByteArray(entity.getBlobField().getBinaryStream());
Upvotes: 2
Reputation: 1828
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.
Bottom line: @Basic(fetch = FetchType.LAZY)
may or may not work, depends on the JPA implementer.
Upvotes: 2
Reputation: 153780
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.
For basic type lazy fetching to work, you need to enable bytecode enhancement and explicitly set the enableLazyInitialization
configuration property to 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>
Upvotes: 14
Reputation: 23
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
Upvotes: 0
Reputation: 643
@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.
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=?
if use repository.save(User)
to add a new User will be ok, but update a User will throw a exception
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.
Upvotes: 3
Reputation: 1
Use FieldHandled with @Basic(fetch=FetchType.LAZY)
works:
public class myFile implements Serializable, FieldHandled
{
private FieldHandler fieldHandler;
@Lob
@Basic(fetch = FetchType.LAZY)
@Column(name = "CONTENT")
protected byte[] content;
Upvotes: 3
Reputation: 16311
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.
Your best bet is to put the Lob into a separate entity, like HtmlSummary
, and use a lazily loaded one-to-one association.
Upvotes: 7
Reputation: 1885
Lazy fetching only applies to references to other entities or collections of entities. It does not apply to values like String or int.
Upvotes: -3