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

时间:2010-09-09 22:15:14

标签: hibernate orm grails

使用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)

4 个答案:

答案 0 :(得分:15)

以下是我对痕迹的理解:

  • 你或某事做findBy
  • triggers一个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的{​​{1}}是increment

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

答案 1 :(得分:9)

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

答案 2 :(得分:1)

@Version
@Column(name = "xxx")
private Integer xxx;

在您的VO中找到@Version注释,并将此列设置为数据库中的默认值;

答案 3 :(得分:0)

<version name="versionID" type="java.lang.Long" unsaved-value="null">
  <column name="version" precision="10" scale="0"/>
</version>

尝试删除unsaved-value =“null”或添加unsved-value =“null”