提问者:小点点

加载惰性列表时的Hibernate惰性初始化异常


我有这两个实体

@Entity
@Table(name = "CallSession")
public class CallSession implements Serializable {

    private long id;
    private List<CallParticipant> members;



    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }


    @OneToMany(mappedBy = "callSession", fetch = FetchType.LAZY)
    public List<CallParticipant> getMembers() {
        return members;
    }

    public void setMembers(List<CallParticipant> members) {
        this.members = members;
    }

}



@Entity
@Table(name = "CallParticipant")
public class CallParticipant implements Serializable {


    private long id;
    private CallSession callSession;
  


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @ManyToOne
    public CallSession getCallSession() {
        return callSession;
    }

    public void setCallSession(CallSession callSession) {
        this.callSession = callSession;
    }

}

但是当我调用CallSession.getMembers()方法时,我会得到以下异常:

无法计算引发“Org.Hibernate.LazyInitializationException”异常的表达式方法。

我搞不懂为什么会出现这个错误? 为什么会出现这个错误,如何修复?


共2个答案

匿名用户

您已经定义了字段members自己,通过在getter上使用fetch=fetchType.lazy来懒惰地获取字段。 事实上,您甚至不必那样做,因为在Hibernate中,每个X对多默认情况下都是懒惰的。

要解决这个问题,您必须使用fetch=fetchType.eager使其成为急切状态,或者更好的方法是编写一个查询,例如在jpql中指定获取策略,如下所示:

@Query("select c from CallSession c left join fetch c.members")

匿名用户

我要从假设你想要你的收藏是懒惰加载开始。

Hibernate的会话可以在很多上下文中关闭,一旦关闭会话,它将无法获取任何懒惰加载的集合。

一般来说,Hibernate非常擅长在web应用上下文中的HTTP线程的生命周期中保持会话打开(spring的“open session in View”)。 会话可能关闭的原因包括对象从一个线程切换到另一个线程,或者对象被缓存,然后被另一个线程访问。

但如果代码在作业或非Web应用程序上下文中运行,则可能会更困难。

1.创建一个repository方法来显式获取集合

使用@queryjoin fetch,添加一个repository方法,该方法显式地渴望加载集合。

2.获取对象后对集合调用.toString()。

这是一个肮脏的黑客,我以前见过很多人在现实世界中使用过。 基本上,在缓存对象或将其移交给执行器或其他线程将访问它的地方之前,对集合调用。toString()来加载它。 通常会留下评论解释原因。

3.将@Transactional添加到既获取数据又访问集合的方法中

除了保持会话活动(例如,数据库操作同时成功和失败)之外,这还有许多其他含义,但是可以快速修复会话活动,例如在作业方法中。

希望这能帮上忙。