Grails 2.1 dateCreated null периодически при сохранении домена
ТЛ: д - р; Это немного связано с проблемой, любые советы приветствуются, заранее рекомендуем прочитать:)
Мои коллеги и я немного боролись со странным поведением в нашем приложении для пакетной обработки. Мы недавно обновили его с 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, где мы больше не видим периодически ошибки в журналах, добавив их в объект Domain.
static mapping = {
autoTimestamp true
}
Но это не единственный домен, который мы наблюдаем при ОДНОМ периодическом сбое сохранения (таким образом, мне нужно добавить сопоставление другим доменам), и если это действительно необходимо для dateCreated
чтобы правильно работать в Grails 2.1, мне нужно добавить его в ОЧЕНЬ больше доменов!
Хуже того, я не могу воспроизвести его в модульном или интеграционном тесте, это происходит только на наших запущенных экземплярах Dev и QA.
Итак, 2 вопроса:
Кто-нибудь знает, почему эта ошибка может возникать периодически?
Если нет, то есть ли способ, которым я могу добавить это глобально
autoTimestamp true
сопоставление со ВСЕМИ объектами домена моего проекта (я не смог найти документацию о том, как добавить его вообще, кроме как установить его вfalse
)
Соответствующий вопрос SO: поля dateCreated, lastUpdated в Grails 2.0
Соответствующее обсуждение Grails Maillist http://grails.1312388.n4.nabble.com/dateCreated-lastUpdated-in-Grails-2-0-td4337894.html
Соответствующие документы Grails для свойств GORM autoTimestamp http://grails.org/doc/latest/guide/GORM.html
2 ответа
Чтобы ответить на оба вопроса:
РЕДАКТИРОВАТЬ Попробуйте
flush: true
в то время какsave
иначеautoTimestamp true
это последнее средство. Я не исследовал, чтобы выяснить причину этой проблемы.Вы можете установить это свойство в
Config.groovy
сделать его применимым для всехdomain
классы.grails.gorm.default.mapping = { autoTimestamp true //or false based on your need }
Вы пытались вручную вставить дату при создании нового 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
}
}
}