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

标签 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 尝试获取这些实体并由于 session 关闭而触发异常(在新的 JSF 请求中调用 equals(),EntityManager 在请求范围内)。

解决方案的人从来没有遇到过那个问题,这就是我向您寻求帮助的原因。

编辑 14.04.2015 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
    }
}

最佳答案

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

您不应该做的一件事是因此更改为 EAGER 加载,因为有一个众所周知的 hibernate bug ,其中在填充字段值之前触发 hashCode 导致更大的困惑

关于Hibernate/JPA 调用 equals() 触发延迟加载异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29607779/

相关文章:

java - 从外部 Jar 文件加载 JPA 实体

spring - 如何将 Oracle 12c 自动身份生成与 Hibernate、Spring 和 JPA 结合使用?

spring - 使用自定义分隔符通过 spring boot 生成 DDL

java - 从 Spring Web 应用程序捕获用户名以供触发器使用

java - 如果属性是实体类型,如何为属性提供值?

java - Spring Boot JPA - ManyToOne关系导致额外的sql

java - 使用 JDBC 初始化类 JPA 实体

java - 了解 Hibernate 获取

java - Spring Boot POSTed JSON 数据验证

java - 使用 Hibernate 的错误 SchemaExport