tl:博士;这有点涉及问题,欢迎任何建议,感谢提前阅读:)
我和我的同事一直在为我们的批处理应用程序中的奇怪行为而苦苦挣扎。我们最近将它从 Grails 1.3.7 升级到 2.1
堆栈跟踪显示以下错误:
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException:
Cannot insert the value NULL into column 'date_created',
table 'dev.dbo.notification_log'; column does not allow nulls. INSERT fails.
...
[quartzScheduler_Worker-1] [||] ERROR hibernate.AssertionFailure - an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
org.hibernate.AssertionFailure: null id in com.virtuwell.domain.NotificationLog entry (don't flush the Session after an exception occurs)
at org.quartz.core.QuartzScheduler.notifyJobListenersWasExecuted(QuartzScheduler.java:1891)
at org.quartz.core.JobRunShell.notifyJobListenersComplete(JobRunShell.java:352)
at org.quartz.core.JobRunShell.run(JobRunShell.java:223)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:546)
[quartzScheduler_Worker-1] [||] ERROR listeners.SessionBinderJobListener - Cannot flush Hibernate Sesssion, error will be ignored
org.hibernate.AssertionFailure: null id in com.virtuwell.domain.NotificationLog entry (don't flush the Session after an exception occurs)
at org.quartz.core.QuartzScheduler.notifyJobListenersWasExecuted(QuartzScheduler.java:1891)
at org.quartz.core.JobRunShell.notifyJobListenersComplete(JobRunShell.java:352)
at org.quartz.core.JobRunShell.run(JobRunShell.java:223)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:546)
这是该特定域对象(NotificationLog)的代码
class NotificationLog implements Serializable{
Date dateCreated
Notification notification
NotificationDeliveryState deliveryState
String message
static mapping = {
message type: 'text'
}
}
然而,奇怪的是,每次持久化域对象时都不会发生此错误,并且我们在代码中只有一个位置会持久化对象,如下所示:
class NotificationLogService {
boolean transactional = true
def logNotification(Notification notification, message, deliveryState) {
def notificationLog = new NotificationLog(
notification: notification,
deliveryState: deliveryState,
message:message
)
try{
notificationLog.save(failOnError:true)
} catch (Exception e) { // Failure to save a notificationLog should not rollback the calling transaction
log.error "NotificationLog State:[$deliveryState] for notification:${notification?.id} did not save. Errors: ${notificationLog?.errors}, Message:$message", e
}
}
}
我们在下面的 SO 问题中发现了一种解决方法的“hack”,通过将其添加到域对象中,我们不再定期在日志中看到错误
static mapping = {
autoTimestamp true
}
但这不是我们看到的唯一一个域,SAME 定期保存失败(因此,我需要将映射添加到其他域),如果这确实是dateCreated
在 Grails 2.1 中正常运行所必需的,我需要将其添加到更多域!
更糟糕的是,我无法在单元或集成测试中重现它,它只发生在我们正在运行的开发和 QA 实例上。
所以,2个问题:
有谁知道为什么这个错误可能会定期发生?
如果没有,有没有办法可以将此映射全局
autoTimestamp true
添加到我项目的所有域对象(除了将其设置为之外,我根本找不到有关如何添加它的文档false
)
相关的 SO 问题: Grails 2.0 中的 dateCreated、lastUpdated 字段
相关 Grails 邮件列表讨论 http://grails.1312388.n4.nabble.com/dateCreated-lastUpdated-in-Grails-2-0-td4337894.html
关于 autoTimestamp GORM 属性的相关 Grails 文档 http://grails.org/doc/latest/guide/GORM.html#eventsAutoTimestamping