Получение исключения groovy.lang.MissingPropertyException при наличии свойства

#grails #groovy

#grails #groovy

Вопрос:

У меня есть класс домена, который работает нормально. Но теперь я добавил Long свойство, и оттуда все идет на юг.

Это случайное определение класса домена:

 class Accident {

    String fullDescription
    Date dateFrom
    Date dateTo
    Long lastUpdated

    Address address
    GpsPosition gpsPosition
    String providerDescription
    String link

    static constraints = {
        address nullable: true
        gpsPosition nullable: true
        providerDescription nullable: true
        link nullable: true
        fullDescription maxSize: 1024
        lastUpdated nullable: true
    }
}
  

И вот тут я получаю ошибку:

 @Transactional
class DatabaseCleanupService {

    static final long timeNotUpdatedToDelete = 1 * 1000 // milliseconds

    void cleanupDatabase() {
        Accident accident

        Accident.each {
            /*ERROR AT THIS LINE*/ if (System.currentTimeMillis() - it.lastUpdated > timeNotUpdatedToDelete) { 
              // do stuff
        }
    }
}
  

Я могу получить доступ к свойству из других частей кода, я успешно печатаю отладочную информацию, но на данный момент она просто вылетает. Что с ним не так?


Редактировать: в сообщении об ошибке говорится следующее:

Такого свойства нет: lastUpdated для класса: com.quarky.nehodyprahaserver.Accident Возможные решения: последнее обновление

Комментарии:

1. Разве вам не нужно: Accident.list().each

2. Бог. Черт возьми. Вы можете записать его 100 раз, но все равно потерпите неудачу в 101-й раз. Спасибо! Отправьте ответ, чтобы я мог его принять

3. Готово 😉 Иногда вам просто нужна вторая пара глаз 😉

Ответ №1:

Сначала вам нужно получить список аварий, изменив:

     Accident.each {
  

Для

     Accident.list().each {
  

Должно это исправить 🙂

Ответ №2:

В зависимости от того, сколько Accident экземпляров имеется в вашей базе данных, вероятно, было бы значительно эффективнее выполнять фильтрацию по дате на уровне базы данных, а не каждый раз извлекать всю таблицу в Groovy objects и фильтровать post-hoc:

 import groovy.time.TimeCategory

@Transactional
class DatabaseCleanupService {

    static final long timeNotUpdatedToDelete = 1 * 1000 // milliseconds

    void cleanupDatabase() {
        use(TimeCategory) {
            Accident.findAllByLastUpdatedLessThan(
              timeNotUpdatedToDelete.milliseconds.ago).each {

                // do stuff
            }
        }
    }
}
  

(или просто встроить константу как 1.second.ago — это выглядит неправильно, когда вы читаете ее как английское «последнее обновление менее одной секунды назад», но это правильно, поскольку LessThan означает «раньше, чем» при применении к Date объектам)

Комментарии:

1. tbh я не знаком с этим методом. метод findAllByLastUpdatedLessThan Groovy автоматически вводится (?)? Как он определяет, когда в последний раз обновлялся элемент? Сохраняет ли оно скрытое поле, установленное для каждого .save(), или я совершенно не прав? 😀

2. findAllBy... Метод представляет собой динамический поиск , который преобразуется в SQL-запрос. И lastUpdated свойство автоматически поддерживается гибернацией (см. Последний абзац раздела руководства пользователя «События и автоматическая временная метка»)

3. @MartinMelka … ах, извините, я вижу, что ваше lastUpdated свойство на самом деле не является обычным автоматически обновляемым — вам следует подумать об изменении его типа на java.util.Date , чтобы воспользоваться этой функцией, или назовите его как-нибудь иначе, если вы не хотите, чтобы его ошибочно приняли за автоматическую временную метку.

4. Не знал о методах findAllBy . Они потрясающие! Если я правильно понимаю, простого наличия Date lastUpdated атрибута внутри класса домена достаточно, чтобы он автоматически заполнялся Hibernate?

5. @MartinMelka да, Date lastUpdated свойство будет обновляться автоматически с учетом времени последнего сохранения объекта в базе данных (по любой причине, будь то явная .save() или неявная проверка на наличие ошибок).