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

懵懂的女人 提交于 2019-11-29 05:42:33

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.

William

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;
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.

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.

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.

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>

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.

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

Lazy fetching only applies to references to other entities or collections of entities. It does not apply to values like String or int.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!