使用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)
答案 0 :(得分:15)
以下是我对痕迹的理解:
findBy
flush
Long
) 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”