Странное NullPointerException с Hibernate и выборкой типа LAZY - PullRequest
3 голосов
/ 03 мая 2019

В нашем приложении я хочу создать отчет.Поэтому загружаются (но не изменяются) несколько экземпляров Foo и связанных Bar объектов.Соответствующие данные берутся из сущностей и хранятся в бинах отчетов для фактической генерации отчетов.Когда транзакция закрывается и возникают ошибки сброса 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) NullPointerException в org.hibernate.internal.util.compare.ComparableComparator.compare(Comparable, Comparable) (оба аргумента null).(Я не могу предоставить трассировку стека для этого, так как я не могу произвести ее во время написания.)

Я получаю одну из трех вышеупомянутых ошибок (или вообще никаких ошибок) при выполнении отчета.Иногда мне нужно вызвать отчет несколько раз, чтобы вызвать ошибку, иногда первый запуск уже генерирует ее.Я не могу понять, что может вызвать такое поведение.

Единственный найденный мной обходной путь - переключить тип выборки обоих показанных атрибутов на EAGER.Тогда все работает хорошо, но это нежелательно, так как количество предварительно выбранных данных велико.

Любая подсказка приветствуется, и если вам нужна дополнительная информация, пожалуйста, дайте мне знать.

В настоящее время мы используемHibernate 4.3.8.Я локально пробовал более новые версии (4.3.11 показывает те же проблемы), но обновление до 5.x является серьезной задачей и может быть выполнено только в короткие сроки, если кто-то может заверить нас, что проблема исправлена ​​(если это на самом деле Hibernateвыпуск) в 5.х.

1 Ответ

1 голос
/ 17 мая 2019

Хорошо, я, наконец, понял, в чем / была проблема:

Поскольку генерация отчетов занимает много времени из-за огромного количества данных, генерация была распараллелена .В части обработки в потоках исполнителя на некоторые объекты ссылались из bean ---, которые на самом деле все еще были Hibernate управляемыми объектами --- и Hibernate не мог разрешить эти proxies (так как session былнедопустимо внутри threads).

Странным является тот факт, что эти проблемы (на самом деле реальные исключения!) были просто видны при установке Hibernate при ведении журнала на trace, и возникающие исключения были не настолько понятныкак базовые!

Это также объясняет, почему генерация отчетов работала корректно, когда режимы выборки были установлены на EAGER.

Мое текущее решение теперь состоит в том, чтобы убедиться, что все необходимые данные изобъекты (в пределах beans) извлекаются до фактической многопоточной обработки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...