Как я могу использовать встроенные классы GORM в Grails?

Следуя документам GORM, я попытался использовать следующий класс домена с Грааль 2.2.1:

package grailscompositiontest

class ScafPerson {
    String name
    ScafAddress homeAddress
    ScafAddress workAddress

    static constraints = {
        name(nullable: false, blank: false)
    }

    static embedded = ['homeAddress', 'workAddress']
}

class ScafAddress {
    String number
    String code
}

Контроллер просто использует строительные леса:

package grailscompositiontest

class ScafPersonController {
    static scaffold = true
}

К сожалению, это не работает, это вызывает ошибку сервера, как только я перехожу к представлению «создать»:

URI:     /GrailsCompositionTest/scafPerson/create
Class:   java.lang.NullPointerException
Message: Cannot get property 'id' on null object

Любая идея, что я делаю неправильно?


person blerontin    schedule 09.04.2013    source источник
comment
Попробуйте сгенерировать скаффолдинг с помощью 'generate-all grailscompositiontest.ScafPerson' и просмотрите сгенерированный код, чтобы увидеть, что не так.   -  person Benoit Wickramarachi    schedule 09.04.2013


Ответы (2)


Я обнаружил, что в документации Grails говорится, что встроенные определения классов нужно помещать либо в тот же исходный файл, что и класс предметной области, либо помещать его в src/groovy. Я поместил Address.groovy в src/groovy и создал пользовательский интерфейс для моего класса Family, который имеет встроенный объект. Сгенерированная страница создания теперь отображается правильно, а поля адреса включены на страницу «Семья». Однако мне все же пришлось изменить поля имени и значения каждого поля формы в сгенерированном файле _form.gsp.

Например, следующий сгенерированный код...

<g:textField name="line1" required="" value="${addressInstance?.line1}"/>

был изменен на...

<g:textField name="address.line1" required="" value="${familyRegistrationInstance.address?.line1}"/>

Где основным объектом домена является класс домена FamilyRegistration (упоминаемый в сгенерированном _form.jsp как familyRegistrationInstance), который имеет встроенный объект Address. Я использую Грааль 2.3.11.

Операция сохранения теперь работает с корректно заполненными полями встроенного объекта. В моем случае это означает, что FamilyRegistration.address заполнен правильно.

Вот соответствующая информация из справочного документа Grails...

«Класс встроенного компонента обычно объявляется в том же исходном файле, что и класс-владелец, или в собственном файле в папке src/groovy. Вы можете поместить класс компонента в папку grails-app/domain, но если вы это сделаете, Grails автоматически создаст выделенная таблица для него. Помещение класса в src/groovy обычно является лучшим вариантом, потому что вы можете использовать этот компонент в нескольких классах предметной области».

http://grails.org/doc/2.2.4/ref/Domain%20Classes/embedded.html

person Nathan Ward    schedule 23.07.2014

Я столкнулся с этой же проблемой на днях. Я считаю, что может быть ошибка в шаблонах, используемых функцией формирования шаблонов. Вы можете либо обновить шаблон, либо, если вы не хотите возиться с шаблонами, запустите generate-all, как упоминал Бенуа, а затем исправьте сгенерированное представление.

Чтобы обновить шаблон:

  1. Grails> шаблоны установки
  2. открыть src/templates/scaffolding/renderEditor.template
  3. найти следующую строку:
    sb << ' value="${' << domainInstance << '.' << property.name << '}"'

и изменить на

    sb << ' value="${' << domainInstance << '?.' << property.name << '}"'

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

  1. grails> сгенерировать все grailscompositiontest.ScafPerson
  2. открыть представления/scafPerson/_form.gsp
  3. искать
    <g:field name="id" type="number" value="${scafAddressInstance.id}" required=""/>
    <g:field name="version" type="number" value="${scafAddressInstance.id}" required=""/>

и изменить на

    <g:field name="id" type="number" value="${scafAddressInstance?.id}" required=""/>
    <g:field name="version" type="number" value="${scafAddressInstance?.id}" required=""/>

Обратите внимание, вы сделаете это дважды, так как у вас есть homeAddress/workAddress

person user553180    schedule 09.04.2013
comment
Спасибо за помощь. Представление создания теперь отображается, но наборы полей homeAddress/workAddress теперь содержат обязательные поля Id и Version. Когда я заполняю все поля и отправляю форму, сервер возвращает ошибку: Property [homeAddress] of class [class grailscompositiontest.ScafPerson] cannot be null Property [workAddress] of class [class grailscompositiontest.ScafPerson] cannot be null - person blerontin; 10.04.2013