Поле формулы Grails не найдено

Этот вопрос касается использования поля формулы в блоке статического отображения в Grails.

Я пытаюсь реализовать очень простой доменный класс, использующий сопоставление формул (производные свойства), но я продолжаю получать "No property found for name [uptime]", где время безотказной работы является производным свойством в доменном классе Grails. Код выглядит следующим образом (упрощенно):

class Derive {
  Integer up
  Integer down

  static mapping = {
    uptime formula : "UP/(DOWN+UP)"
  }
}

class DeriveTests extends GroovyTestCase {

    void testDerivedProp() {
      new Derive(up:10, down:5).save()
      new Derive(up:5, down:5).save()
      assertEquals Derive.all.size(),2

      assertEquals 2,Derive.findAllByUptimeGreaterThan(0.1).size() //fails here
      assertEquals 2,Derive.findAllByUptimeGreaterThan(10/(10+5)).size()
    }
}

Запуск теста дает мне ошибку во втором assertEquals: org.codehaus.groovy.grails.exceptions.InvalidPropertyException: No property found for name [uptime] for class [class Derive]. Я не могу понять, что я здесь делаю неправильно, поскольку ознакомился как с Grails In Action, так и с ссылаться на документы несколько раз.

Любые подсказки относительно того, что я делаю неправильно? База данных резервного копирования — это HSQLDB, работающая в памяти с настройками по умолчанию (созданная приложением Grails create-app).

редактировать: я немного не уверен, должен ли я добавить поле свойства для формулы или нет. Если я добавлю поле свойства «Двойное время безотказной работы», утверждение все равно завершится ошибкой, но на этот раз потому, что время безотказной работы равно 0. Просмотр объекта в отладчике показывает, что время безотказной работы равно нулю. Тем не менее, вывод sql показывает мне то, что выглядит правильно: hibernate.SQL select this_.id as id6_0_, this_.version as version6_0_, this_.down as down6_0_, this_.up as up6_0_, this_.UP*100/(this_.DOWN+this_.UP) as formula0_0_ from derive this_


person oligofren    schedule 03.05.2011    source источник
comment
Кажется, я решил это. В некотором роде. Чтобы заставить его работать, мне нужно добавить поле, называемое временем безотказной работы, которое является двойным. Я бы подумал, что этого должно быть достаточно, поскольку число, возвращаемое делением в формуле, является числом с плавающей запятой, но кажется, что применяются обычные правила целочисленного деления, поскольку результат всегда равен нулю. Поэтому, чтобы тесты работали, мне нужно указать, что все три поля являются двойными. Несмотря на то, что все работает, запрос объекта для получения производного значения все равно даст вам ноль. Иди разберись.   -  person oligofren    schedule 03.05.2011
comment
Я понял, почему он возвращает значение null для свойства. Смотрите последний комментарий от меня под ответом Зиада Джаюси.   -  person oligofren    schedule 04.05.2011


Ответы (2)


Давно не было новых ответов, поэтому подвожу итоги:

  • Для того, чтобы формула работала, должно быть поле для формулы.
  • Производное свойство всегда доступно для поиска, так как это связано с поиском в базе данных, но свойство объекта всегда будет пустым, если сохраненная версия все еще находится в кэше. Вкратце: очистите кеш сеанса перед поиском или обновите кешированный объект (obj.refresh())

Последний бит, обновление вручную, кажется очень неэлегантным, но я не нашел способа обойти это.

person oligofren    schedule 09.06.2011

Во-первых: время безотказной работы не является ни примитивным, ни типом класса. также Не уверен, почему вы используете отображение в этом отношении. в качестве альтернативы вы можете создать временное свойство «время безотказной работы» в своем классе, а затем дать ему метод получения:

я бы использовал Double вместо Integer:

class Derive {
    Integer up
    Integer down
    static transients = ['uptime']

    Integer getUptime(){
      Integer uptime = up/(down+up)    
      return uptime
    }
}

затем для доступа к нему в вашем коде:

def derive = new Derive()
def uptime = derive.uptime
person z.eljayyo    schedule 03.05.2011
comment
Что вы подразумеваете под временем безотказной работы, которое не является примитивным или типом класса? Вы имеете в виду, что он не типизирован? Если да, то должен ли я добавить в класс поле с его именем и типом? - person oligofren; 03.05.2011
comment
Что касается того, почему ... обычно просто делать что-то простое, чтобы знать, что это работает, для меня достаточно ценно. - person oligofren; 03.05.2011
comment
class Derive { Двойное увеличение Двойное уменьшение Двойное время безотказной работы ... Любая идея, почему это тоже не работает? Здесь нет целочисленного деления, но я все равно просто получаю 0/null в тестах. - person oligofren; 03.05.2011
comment
да время безотказной работы это не тип и не класс. вы присвоили значения вверх + вниз? похоже, что общее значение для вверх + вниз равно нулю, а 0/нулевое исключение вызывает исключение. тщательно проверьте свой код. - person z.eljayyo; 03.05.2011
comment
также взгляните на это, чтобы использовать формулу, в вашем коде вы не объявили время безотказной работы: jira.grails .org/browse/GRAILS-5688 - person z.eljayyo; 03.05.2011
comment
Спасибо, Зиад! Хотя я не думаю, что вы читали комментарий под исходным ответом, так как это сделало ваш комментарий несколько излишним :) Что касается вашего вопроса: конечно, я присвоил значения вверх + вниз. Вы можете сами увидеть код выше. вверх и вниз присваиваются значения при создании объекта. Единственная действительно странная вещь здесь заключается в том, что я могу использовать вычисленное значение в поиске findBy*, но я не могу получить доступ к значению напрямую. ЭТО МЕНЯ ЗАНИМАЕТ. - person oligofren; 04.05.2011
comment
Кстати, я вставил краткий (но работоспособный) пример на pastebin, который более кратко описывает проблему: pastebin.ca/2053623 - person oligofren; 04.05.2011
comment
Хм... ваша версия с геттером не будет работать с HQL или мета-запросами типа findAllBy... Вот почему использовались производные свойства. Я задал вопрос в списке рассылки Grails (goo.gl/y4ogF) и после создания нескольких тестов (доступных на pastebin: pastebin.ca/2053745), вот что я обнаружил: производное свойство всегда доступно для поиска , так как это включало поиск по базе данных. Производное свойство объекта всегда будет иметь значение null, если сохраненная версия все еще находится в кэше. Вкратце: очистите кеш сеанса перед поиском или обновите кешированный объект (obj.refresh()) - person oligofren; 04.05.2011