java - 带有 Hibernate 和获取类型 LAZY 的奇怪 NullPointerException

标签 java hibernate

在我们的应用程序中,我想生成一份报告。因此 Foo 和关联的 Bar 实体的多个实例被加载(但未更改)。相关数据取自实体并存储在报告 bean 中以用于实际报告生成。当事务关闭并发生 Hibernate 刷新错误时(见下文)。

除了其他属性,Foo 还持有对Bar 的引用。这是两个类的摘录:

@Entity
@Table(name = "FOO")
public class Foo {

    @Column(name = "BAR_ID")
    private Long barId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(insertable = false, updatable = false)
    private Bar bar;

    public Long getBarId() {
        return barId;
    }

    public void setBarId(Long barId) {
        this.barId = barId;
    }

    public Bar getBar() {
        return bar;
    }

    // no setter for "bar"

    // other attributes
}

@Entity
@Table(name = "BAR")
public class Bar {

    @OneToMany(mappedBy = "bar", fetch = LAZY)
    private List<Foo> foos;

    // no getter/setter for "foos"

    // other attributes
}

具有各种其他操作(包括创建、编辑、删除上述实体)的整个应用程序完美无缺,但在创建报告时出现奇怪的错误:

1)

org.springframework.orm.hibernate4.HibernateSystemException: Found two representations of same collection: Bar.foos; nested exception is org.hibernate.HibernateException: Found two representations of same collection: Bar.foos
    at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:216)
    at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:681)
    at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:563)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
    at de.ba.wws.aop.TransactionTimeAspect.setTransactionTime(TransactionTimeAspect.java:20)
[...]
Caused by: org.hibernate.HibernateException: Found two representations of same collection: Bar.foos
    at org.hibernate.engine.internal.Collections.processReachableCollection(Collections.java:170)
    at org.hibernate.event.internal.FlushVisitor.processCollection(FlushVisitor.java:59)
    at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:121)
    at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:82)
    at org.hibernate.event.internal.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:76)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:172)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:231)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:102)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:55)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
    at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:555)
    ... 119 more

2)

java.lang.NullPointerException
    at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:155)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:91)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:55)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
    at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:555)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85)
    at de.ba.wws.aop.TransactionTimeAspect.setTransactionTime(TransactionTimeAspect.java:20)
    [...]

3) org.hibernate.internal.util.compare.ComparableComparator.compare(Comparable, Comparable) 中的 NullPointerException(两个参数 null ). (我无法为此提供堆栈跟踪,因为在撰写本文时我无法生成它。)

我在执行报告时遇到上述三个错误之一(或根本没有错误)。有时我需要多次调用报告才能产生错误,有时第一次运行就已经产生错误。我无法弄清楚是什么导致了这种行为。

我发现的唯一解决方法是将显示的both 属性的获取类型切换为EAGER。然后一切正常,但由于预取的数据量很大,所以并不理想。

欢迎任何提示,如果您需要任何进一步的详细信息,请告诉我。

我们目前使用的是 Hibernate 4.3.8。我在本地尝试了较新的版本(4.3.11 显示了相同的问题),但是升级到 5.x 是一项主要任务,并且只有在有人可以向我们保证问题已解决(如果它实际上是 Hibernate)的情况下才能在短时间内完成问题)在 5.x 中。

最佳答案

好吧,我终于明白问题是什么了:

由于数据量巨大,报告生成需要花费大量时间,因此生成并行。在执行程序线程的处理部分中,一些对象从 bean 中引用——它们实际上仍然是 Hibernate 管理的实体——和 Hibernate 无法解析那些 proxies(因为 sessionthreads 中无效)。

奇怪的是,当将 Hibernate 日志记录设置为 trace 时,这些问题(实际上是真正的异常!)才可见,并且由此产生的异常并不像底层的!

这也解释了为什么当获取模式设置为 EAGER 时报告生成工作正常。

我目前的解决方案是确保在实际多线程处理之前从实体(在 beans 中)获取所有需要的数据。

关于java - 带有 Hibernate 和获取类型 LAZY 的奇怪 NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55969440/

相关文章:

image - 如何使用spring mvc显示mysql数据库中的图像

java - Hibernate 查询之类的问题

java - Hibernate NOWAIT 不适用于 SQL Server 2008

java - org.hibernate.TypeMismatchException : Provided id of the wrong type

java - 有没有办法从不同的方法访问数组?

java - 如何在 Java 中从 .txt 文件读取字符串?

java - 在游戏中输入!日期和时间?

java - 如何在 Play Framework 模型中导入 java 扩展?

java - 如何在没有 hibernate.cfg.xml 文件的情况下创建 Hibernate session ?

java - 如何使用 gridControl 组件获取替代行颜色