Halsnate / JPA调用equals()会触发延迟加载异常

时间:2015-04-13 14:25:07

标签: hibernate jpa

我已按照older topic on stackoverflow中的建议实施了 equals() / hashCode()方法。这种方法的问题是例外

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:160) [hibernate-core-4.1.6.Final.jar:4.1.6.Final]
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:259) [hibernate-core-4.1.6.Final.jar:4.1.6.Final]
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185) [hibernate-core-4.1.6.Final.jar:4.1.6.Final]
    at pkg.db.TblChain_$$_javassist_815.equals(TblChain_$$_javassist_815.java) [classes:]
    [...]
在调用 equals()之前抛出的

。它只发生在实体有例如其他实体的外键。 Hibernate尝试获取这些实体并触发异常,因为关闭会话(在新的JSF请求中调用equals(),EntityManager是请求作用域)。

解决方案的人从未遇到过这个问题,这就是我向你寻求帮助的原因。

编辑2015年4月14日14:50: equals()都是使用实体的ID实现的。但是对于这个例子,我用简单的返回替换了它的实现,因为它没关系。我发现如果我在外来实体(tblChain)中有另一个外来实体(例如tblChainType)并不重要。如果在用于加载的实体管理器处于活动状态时未使用第一个,则它将始终失败。

// Entity classes
public class TblChainInstance {
    private TblChain tblChain; // Foreign entity

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "intChainId", nullable = false)
    public TblChain getTblChain() {
        return this.tblChain;
    }

    public boolean equals(Object other) {
        return false; // doesn't matter, what I have here. 
                      // It always works if this is the selected Entity.
    }
}

public class TblChain {
    public boolean equals(Object other) {
        return false; // doesn't matter, what I have here. 
                      // It always throws a LazyInitializationException
    }
}

// Testcode
@Named @ViewScoped
public class MyBean implements Serializable {
    private TblChainInstance _tblChainInstance;

    @PostConstruct
    public void _init() {
        _tblChainInstance = new JPAQuery(_entityManager).from(qtChainInstance)
            .limit(1).singleResult(qtChainInstance);
    }

    public void actionListener() {
        System.out.println(_tblChainInstance.equals(1)); // outputs false
        System.out.println(_tblChainInstance.getTblChain().equals(1)); // throws
    }
}

2 个答案:

答案 0 :(得分:1)

希望我能理解你的问题。

要么避免延迟加载并强制执行,这将在同一个查询期间获取结果或修改你的equals和hashcode方法

希望这些帮助(建议在外键关系的情况下编写方法); Should I write equals() methods in JPA entities? https://developer.jboss.org/wiki/EqualsandHashCode?_sscc=t

答案 1 :(得分:1)

为了补充@ Godwin的答案,我会更改equalshashCode,以便在对象附加到持久上下文以及分离时的情况下它们都是可靠的。这意味着您应该避免任何关联的对象或自动生成的Id。 @Godwin提供的链接解释了这一切,它的摘要是你应该尝试找到一个自然键,(例如用户实体中的电子邮件等)

你不应该做的一件事就是更改为EAGER加载,因为有一个众所周知的休眠bug,其中hashCode在填充字段值之前被触发,导致更大的混乱