简体   繁体   中英

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). The relevant data is taken from the entities and stored in report beans for actual report generation. When the transaction is closed and Hibernate flushes errors occur (see below).

Besides other attributes, Foo holds a reference to 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)

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) NullPointerException in org.hibernate.internal.util.compare.ComparableComparator.compare(Comparable, Comparable) (both arguments 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 . 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. 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.

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 ).

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!

This also explains, why the report generation worked gracefully when fetch modes were set to 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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