简体   繁体   English

奇怪的NullPointerException与Hibernate和获取类型LAZY

[英]Strange NullPointerException with Hibernate and fetch type LAZY

In our application I want to generate a report. 在我们的应用程序中,我想生成一个报告。 Therefore multiple instances of Foo and associated Bar entities are loaded (but not changed). 因此,加载了多个Foo实例和关联的Bar实体(但未更改)。 The relevant data is taken from the entities and stored in report beans for actual report generation. 相关数据来自实体并存储在报告bean中以生成实际报告。 When the transaction is closed and Hibernate flushes errors occur (see below). 当事务关闭并且Hibernate刷新时发生错误(见下文)。

Besides other attributes, Foo holds a reference to Bar . 除了其他属性, Foo还提到了Bar This is an extract of both classes: 这是两个类的摘录:

@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
}

The whole application with various other operations (including creation, editing, deleting of the aforementioned entities) works flawless, but upon report creation I get strange errors: 整个应用程序与各种其他操作(包括创建,编辑,删除上述实体)完美无瑕,但在创建报表时我得到了奇怪的错误:

1) 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) 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) NullPointerException in org.hibernate.internal.util.compare.ComparableComparator.compare(Comparable, Comparable) (both arguments null ). 3) org.hibernate.internal.util.compare.ComparableComparator.compare(Comparable, Comparable) NullPointerException org.hibernate.internal.util.compare.ComparableComparator.compare(Comparable, Comparable) (两个参数为null )。 (I cannot provide a stack trace for this one as I cannot produce it at the time of writing.) (我不能为这个提供堆栈跟踪,因为我在撰写本文时无法生成它。)

I get one of the three above errors (or no error at all) upon executing the report. 执行报告后,我得到上述三个错误之一(或根本没有错误)。 Sometimes I need to call the report multiple times to produce an error, sometimes the first run already generates one. 有时我需要多次调用报告以产生错误,有时第一次运行已生成一个错误。 I'm not able to figure out what might cause this behaviour. 我无法弄清楚可能导致这种行为的原因。

The only workaround I found is to switch the fetch type of both shown attributes to EAGER . 我找到的唯一解决方法是将两个显示属性的获取类型切换为EAGER Then everything works well, but is not desired as the prefetched data amount is high. 然后一切运行良好,但由于预取数据量很高,因此不需要。

Every hint is welcome and if you need any further details, please let me know. 欢迎提出每一个提示,如果您需要任何进一步的细节,请告诉我。

We are currently using Hibernate 4.3.8. 我们目前正在使用Hibernate 4.3.8。 I locally tried newer versions (4.3.11 shows the same problems), but upgrading to 5.x is a major task and can only be accomplished in a short timeframe if anyone can assure us that the problem is fixed (if it's actually a Hibernate issue) in 5.x. 我在本地尝试过较新版本(4.3.11显示相同的问题),但升级到5.x是一项重大任务,只能在短时间内完成,如果有人可以向我们保证问题得到解决(如果它实际上是一个Hibernate)问题)在5.x.

Ok, I finally understood what is/was the problem: 好的,我终于明白了问题是什么?

As the report generation takes a lot of time due to the huge amount of data, generation was parallelized . 由于大量数据导致报告生成花费了大量时间,因此生成并行化 Within the processing portion in the executor threads some objects were referenced from the bean ---which were actually still Hibernate managed entities---and Hibernate could not resolve those proxies (as the session was not valid inside the threads ). 在执行程序线程的处理部分中,一些对象是从bean引用的 - 它们实际上仍然是Hibernate管理实体 - 而Hibernate无法解析这些proxies (因为sessionthreads内部无效)。

Strange is the fact, that those problems (actually real exceptions!) were just visible when setting Hibernate logging to trace and the resulting exceptions were not that understandable as the underlying ones! 奇怪的是,当将Hibernate日志记录设置为trace时,这些问题(实际上是真正的例外!)只是可见的,并且结果异常不像底层的那样可以理解!

This also explains, why the report generation worked gracefully when fetch modes were set to EAGER . 这也解释了为什么当获取模式设置为EAGER时报告生成工作正常。

My current solution now is to make sure all needed data from the entities (within the beans ) are fetched before actual multi-threaded processing. 我现在的解决方案是确保实际的多线程处理之前获取实体( beans )所需的所有数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM