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 вопроса:

  1. Кто-нибудь знает, почему эта ошибка может возникать периодически?

  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 ответа

Чтобы ответить на оба вопроса:

  1. РЕДАКТИРОВАТЬ Попробуйте flush: true в то время как save иначе autoTimestamp true это последнее средство. Я не исследовал, чтобы выяснить причину этой проблемы.

  2. Вы можете установить это свойство в 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
    }


}

}

Другие вопросы по тегам