代码之家  ›  专栏  ›  技术社区  ›  Charlie Martin

grails/hibernate:版本控制上的空指针异常

  •  15
  • Charlie Martin  · 技术社区  · 14 年前

    使用Grails中的遗留代码库。在某些情况下(我们不清楚具体是什么),我们得到一个神秘的NPE,堆栈跟踪如下,同时执行findby。

    到目前为止,我们有点陷入困境;这出现在几个冬眠的论坛中,但回答似乎是“你的模式出了问题”。找到一些额外的细节来帮助我们跟踪问题是很好的。

    更新

    谢谢你的回答。是的,很明显,在这种不良事件发生的时候, version 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 回复  |  直到 7 年前
        1
  •  15
  •   Pascal Thivent    14 年前

    以下是我对痕迹的理解:

    • 你或是做什么 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 传递给 increment null .

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

        2
  •  9
  •   BlueLettuce16    13 年前

    我也有同样的问题。这是旧数据库记录的问题。您已经在数据库表中添加了version列,并在VO中添加了@version注释,对于在该chagne之后创建的新对象,它可以正常工作,但是对于旧对象失败-此列中的值为空。解决方案是用0(或根据数据类型的不同值)更新所有旧对象的版本列。希望能有所帮助。

        3
  •  1
  •   qiulvelu    7 年前
    @Version
    @Column(name = "xxx")
    private Integer xxx;
    

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

        4
  •  0
  •   Ravi Parekh    14 年前
    <version name="versionID" type="java.lang.Long" unsaved-value="null">
      <column name="version" precision="10" scale="0"/>
    </version>
    

    尝试删除未保存的value=“null”或添加未保存的value=“null”