【问题标题】:Grails 4: Save doesn't work in service method with prefix 'set'Grails 4:保存在前缀为“set”的服务方法中不起作用
【发布时间】:2021-12-31 11:03:15
【问题描述】:

使用 Grails 4.0.11 和 OpenJDK 11,我遇到了一个非常奇怪的行为,我可以将其提取到一个独立项目中,并确保它与插件无关:

Given 是一个控制器:

def updateOrder() { 
  def order = Order.get(params.id)
  def result = shopService.setOrderPrintFileChecked(order)
  redirect(action: "detailOrder", id: order.id)
}

和服务

@Transactional
class ShopService {
    def setOrderPrintFileChecked(Order order) {
        order.printFileChecked = new Date()
        println("Validate: " + order.validate())
        println("Errors: " + order.errors)
        println("Dirty: " + order.isDirty())
        def r = order.save(failOnError: true)
        println("Result: " + r.printFileChecked)
        return true
    }
}

这不会将值保存到数据库中(尝试 MySQL+H2 默认数据库)。 如果显示:

Validate: true
Errors: org.grails.datastore.mapping.validation.ValidationErrors: 0 errors
Dirty: true
Result: Sun Nov 21 15:58:17 CET 2021

如果我将 ShopService 的方法从 setOrderPrintFileChecked() 更改为 setorderPrintFileChecked() 甚至 test(),它会起作用并且值正在正确保存。**

似乎前缀 + camelCase "setXyz" 有不同的行为。我想知道它是什么以及如何修复/防止这种情况。可以提供完整的演示应用程序的行为。

** 更新** 这是一个非 setter 名称的反编译服务类:

    public Object updateMyValue(final Order order) {
        final Reference order2 = new Reference((Object)order);
        final CustomizableRollbackTransactionAttribute $transactionAttribute = new CustomizableRollbackTransactionAttribute();
        $transactionAttribute.setName("ch.pacdesigner.ShopService.updateMyValue");
        final GrailsTransactionTemplate $transactionTemplate = new GrailsTransactionTemplate(this.getTransactionManager(), $transactionAttribute);
        return $transactionTemplate.execute((Closure)new ShopService._updateMyValue_closure1((Object)this, (Object)this, order2));
    }

这是编译后的方法

    public Object setOrderPrintFileChecked(final Order order) {
        final CallSite[] $getCallSiteArray = $getCallSiteArray();
        ScriptBytecodeAdapter.setGroovyObjectProperty($getCallSiteArray[0].callConstructor((Object)Date.class), (Class)ShopService.class, (GroovyObject)order, (String)"printFileChecked");
        $getCallSiteArray[1].call((Object)order, (Object)ScriptBytecodeAdapter.createMap(new Object[] { "failOnError", true }));
        return true;
    }

【问题讨论】:

  • 我刚刚遇到了一个类似的问题,所以我猜这与 Grails 修改设置器以处理脏检查有关。如果您想进一步检查它,请谷歌“grails setter dirty”。我会尝试 order.setPrintFileChecked(new Date()) 看看这是否适用于所有示例。
  • 反编译的“setOrderPrintFileChecked”方法里面有事务管理指令吗?
  • @JeffScottBrown 我尝试了不同的方法名称,但方法始终相同,命名为“setOrderPrintFileChecked”或“holaSullivan”。如果我将“@Transactional”添加到方法头,它可以与“setOrderPrintFileChecked”一起使用——但如果我将它添加到服务中,它应该对任何方法都有效。如果我添加“withTransaction”块,它也可以工作。但这不是 DRY IMHO 的想法。
  • "我尝试了不同的方法名,方法总是一样" - setOrderPrintFileChecked中的反编译指令中是否有事务管理逻辑?
  • 您没有显示足够的代码来确定,但看起来您正在开始事务之前从数据库中检索实体。是这样吗?

标签: grails grails-orm


【解决方案1】:
猜你喜欢
  • 2017-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-08
  • 1970-01-01
  • 1970-01-01
  • 2016-06-21
相关资源
最近更新 更多