Grails / Hibernate: исключение нулевого указателя при управлении версиями - PullRequest
16 голосов
/ 10 сентября 2010

Работа с устаревшей кодовой базой в Grails. При некоторых условиях (нам неясно, что именно) мы получаем таинственный NPE, след стека, как показано ниже, при выполнении findBy.

До сих пор мы были в тупике; это появляется на нескольких форумах для Hibernate, но ответы, похоже, сводятся к «что-то не так с вашей схемой». Было бы замечательно найти некоторые дополнительные детали, которые помогут нам отследить проблему.

Обновление

Спасибо за ответ. Да, ясно, что в тот момент, когда происходит этот NPE, version равен null. Проблема в том, что когда мы смотрим на это в коде, это , а не null.

Мы начали подозревать, что есть проблема с многопоточностью.

Caused by: java.lang.NullPointerException
    at org.hibernate.type.LongType.next(LongType.java:79)
    at org.hibernate.engine.Versioning.increment(Versioning.java:131)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.getNextVersion(DefaultFlushEntityEventListener.java:387)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:279)
    at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:151)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:49)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
    at org.codehaus.groovy.grails.plugins.quartz.listeners.SessionBinderJobListener.jobWasExecuted(SessionBinderJobListener.java:58)
    at org.quartz.core.QuartzScheduler.notifyJobListenersWasExecuted(QuartzScheduler.java:1910)

Ответы [ 4 ]

17 голосов
/ 10 сентября 2010

Вот мое понимание следа:

  • Вы или что-то делаете findBy
  • это триггеры flush
  • сеанс содержит грязный объект с полем версии (типа Long), который необходимо обновить
  • Hibernate пытается получить следующее значение для поля версии для обновления
  • и вот где вы получаете NPE

. Тело org.hibernate.engine.Versioning.increment(Versioning.java:131):

public static Object increment(Object version, VersionType versionType, SessionImplementor session) {
    Object next = versionType.next( version, session ); // line 131
    if ( log.isTraceEnabled() ) {
        log.trace(
                "Incrementing: " +
                versionType.toLoggableString( version, session.getFactory() ) +
                " to " +
                versionType.toLoggableString( next, session.getFactory() )
        );
    }
    return next;
}

И тело org.hibernate.type.LongType.next(LongType.java:79) (которое обеспечивает реализацию вышеуказанного versionType.next):

public Object next(Object current, SessionImplementor session) {
    return new Long( ( (Long) current ).longValue() + 1 ); // line 79
}

Кажется очевидным, что version, переданное increment, равно null.

Таким образом, я бы искал в базе данных запись со значением NULL в столбце версии.Активация ведения журнала SQL может помочь сузить поиск.

9 голосов
/ 12 января 2012

У меня была такая же проблема. Это проблема со старыми записями базы данных. Вы добавили столбец версии в таблицу базы данных и аннотацию @Version в VO, и он отлично работает для новых объектов, созданных после этого этапа, однако для старых объектов он не работает - значение в этом столбце равно нулю. Решение состоит в том, чтобы обновить все старые объекты - их столбец версии с 0 (или другим значением в зависимости от типа данных). Надеюсь, это поможет.

1 голос
/ 27 февраля 2018
@Version
@Column(name = "xxx")
private Integer xxx;

найдите аннотацию @Version в вашем VO и установите для этого столбца значение по умолчанию в базе данных;

0 голосов
/ 26 февраля 2011
<version name="versionID" type="java.lang.Long" unsaved-value="null">
  <column name="version" precision="10" scale="0"/>
</version>

попробуйте удалить unsaved-value = "null" или добавить unsved-value = "null"

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