tl:dr; 这有点涉及问题,欢迎任何建议,感谢提前阅读:)
我的同事和我在批量处理应用程序中遇到了一些奇怪的行为。我们最近将它从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中,我需要将其添加到更多域中!
更糟糕的是,我无法在单元或集成测试中重现它,它只发生在我们正在运行的Dev和QA实例上。
有谁知道为什么会出现这种错误?
如果没有,是否有办法全局将此autoTimestamp true
映射添加到我项目的所有域对象中(我一直无法找到有关如何使用的文档添加它,除了将其设置为false
)
相关SO问题: dateCreated, lastUpdated fields in Grails 2.0
相关Grails Maillist讨论 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
答案 0 :(得分:3)
回答这两个问题:
编辑在flush: true
时尝试save
,否则autoTimestamp true
是最后的选择。我没有研究找出这个问题的原因。
您可以在Config.groovy
中设置此属性,使其适用于所有domain
类。
grails.gorm.default.mapping = {
autoTimestamp true //or false based on your need
}
答案 1 :(得分:0)
您是否尝试在创建新NotificationLog时手动插入日期? 像这样:
class NotificationLogService {
boolean transactional = true
def logNotification(Notification notification, message, deliveryState) {
def notificationLog = new NotificationLog(
dateCreated: new Date(),
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
}
}
}