Grails/Hibernate:版本控制时出现空指针异常

Cha*_*tin 16 orm grails hibernate

使用Grails中的遗留代码库.在某些条件下(我们还不清楚到底是什么)我们得到一个神秘的NPE,堆栈跟踪如下,同时做一个findBy.

到目前为止,我们有点受阻; 这出现在Hibernate的几个论坛上,但回应似乎归结为"你的架构出了问题".找到一些额外的细节来帮助我们追踪问题会很棒.

更新

谢谢你的回答.是的,很明显,在这个NPE发生的时候,versionnull.麻烦的是,当我们在代码中查看它时,它不是 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)
Run Code Online (Sandbox Code Playgroud)

Pas*_*ent 18

以下是我对跟踪的理解:

  • 你或者别的什么 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;
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

它似乎很清楚的是,version传递到incrementnull.

因此,我会在数据库中查找NULL其版本列中具有值的记录.激活SQL日志记录可能有助于缩小搜索范围.


Blu*_*e16 9

我有同样的问题.这是旧数据库记录的问题.您已在数据库表中添加了版本列,并在VO中添加了@Version注释,它适用于在该chagne之后创建的新对象,但是对于旧对象失败 - 此列中的值为null.解决方案是更新所有旧对象 - 它们的版本列为0(或某些不同的值,具体取决于数据类型).我希望它有所帮助.