Grails 2.2.4 > Домен в объекте команды: сбой привязки
Я пытаюсь использовать Домен (Заказ) с 3-мя односторонними связями (Продукт, Дефект и Решение) в CommandObject для выполнения обновления, и я получаю 3 различных поведения:
- cmd.order.product получает новое значение;
- cmd.order.defect также получает новое значение (но позже оно вызывает HibernateException);
- cmd.order.solution полностью игнорируется;
Хорошо, это среда:
- Groovy: 2.3.7
- JVM: 1.7.0_71 Поставщик: Корпорация Oracle ОС: Mac OS X
- Грааль 2.2.4
И это актеры:
class Order {
Product product
Defect defect
Solution solution
static constraints = {
product nullable: true
defect nullable: true
solution nullable: true, validator: { val, obj, errors ->
if (val && !obj.defect) {
errors.rejectValue 'solution', 'defect.dequired', [val.name] as Object[], null
}
}
}
}
@Validateable
class OrderCommand {
Order order
static constraints = {
order nullable:false
}
}
class OrderController {
...
def update(final OrderCommand cmd) {
def instance = cmd.order
println params
log.debug "cmd.errors: '${cmd.errors}'"
log.debug "instance.errors: '${instance.errors}'"
log.debug "instance.product.id: '${instance.product?.id}', params.order.product.id: '${params.order?.product?.id}'"
log.debug "instance.defect.id: '${instance.defect?.id}', params.order.defect.id: '${params.order?.defect?.id}'"
log.debug "instance.solution.id: '${instance.solution?.id}', params.order.solution.id: '${params.order?.solution?.id}'"
if(!cmd.hasErrors() && instance.validate()) {
instance = instance.save validate:false, failOnError:true
this.flashDefaultMessageUpdated Order.class
}
}
...
}
И это форма, представленная (Сорта..):
<form action="/foo/order/update" method="post">
<input type="hidden" id="orderId" name="order.id" value="257132">
<select id="product" name="order.product.id">
<option value="null">Select…</option>
<option value="36">PRODUCT 1</option>
...
</select>
<select id="defect" name="order.defect.id">
<option value="null">Select…</option>
<option value="49">DEFECT 1</option>
...
</select>
<select id="solution" name="order.solution.id">
<option value="null">Select…</option>
<option value="6">SOLUTION 1</option>
...
</select>
...
</form>
Теперь, с учетом существующего Ордена, для "экземпляра" (HA!):
def orderInstance = Order.get 257132l
println orderInstance
//[id:257132, product:[id:36], defect:[id:4], solution:null]
После отправки в '/foo/order/update' получены следующие параметры:
println params
/*
[action:update, controller:order,
order:[
id:257132,
solution.id:1,
solution:[id:1],
defect.id:49,
defect:[id:49],
product.id:31,
product:[id:31]
],
order.defect.id:49,
order.id:257132,
order.product.id:31,
order.solution.id:1,
version:33]
*/
Но объект привязан довольно странно, проверьте это:
log.debug..
/*
//DEBUG cmd.errors: '0 errors'
//DEBUG instance.errors: '0 errors'
//DEBUG instance.product.id: '31', params.order.product.id: '31' [OK]
//DEBUG instance.defect.id: '49', params.order.defect.id: '49' [OK]
//DEBUG instance.solution.id: 'null', params.order.solution.id: '1' [??]
*/
То есть новые значения продукта и дефекта были получены правильно, тогда как новое значение решения было просто проигнорировано.
Как ни странно, при попытке выполнить обновление выдается следующее исключение:
org.hibernate.HibernateException:
identifier of an instance of com.foo.domain.Defect was altered from 4 to 49
Есть идеи?
Я уже боюсь за свое здравомыслие.
Приветствия.