【问题标题】:Grails 2.5, beforeDelete cannot access one-to-many relationshipGrails 2.5,beforeDelete 无法访问一对多关系
【发布时间】:2020-02-28 13:40:14
【问题描述】:

在此处使用 Grails 2.5.6。我试图在 beforeDelete GORM 事件中从我的域类中访问一组字符串。我什至在 beforeDelete 中到达我的断点之前,就在数据库日志中看到了对这个集合的删除。

我在域类中的 println(strings) 上收到 NullPointerException。

我的测试域类看起来像

class DeleteTest {
    Integer id
    Set<String> stringSet
    String prop1
    String prop2

    static hasMany = [stringSet: String]

    static constraints = {
        prop1(maxSize: 20)
        prop2(maxSize: 20)
    }

    static mapping = {
        stringSet(joinTable: [column: 'delete_test_string_set', length: 15])
    }

    def beforeDelete() {
        withNewSession {
            Set<String> strings = this."stringSet"
            println(strings)
        }
    }
}

我已经做了一个这样的测试控制器。

class DeleteTestController {

    def create() {
        DeleteTest test = null
        DeleteTest.withTransaction {
            test = new DeleteTest(
                    prop1: 'Test',
                    prop2: 'another test',
                    stringSet: ['str1', 'str2', 'str3']
            ).save()
        }

        render (test as JSON)
    }

    def delete() {
        DeleteTest test = DeleteTest.findByProp1('Test')
        DeleteTest.withTransaction {
            test.delete()
        }

        render(test as JSON)
    }
}

如何在 beforeDelete 事件中获取我的 stringSet?

【问题讨论】:

  • “我的 println(strings) 上出现 NullPointerException” - 你是说如果 stringsnullprintln(strings) 正在抛出 NullPointerException

标签: grails groovy grails-orm


【解决方案1】:

一种简单的方法是确保在调用删除之前加载stringSet。但是,这里显然发生了一些奇怪的行为,我将描述到目前为止我发现的情况。

简单回答

def delete() {
    DeleteTest test = DeleteTest.findByProp1('Test')
    test.stringSet?.size() // <-- force load here
    DeleteTest.withTransaction {
        test.delete()
    }
    render(test as JSON)
}

其他注意事项

我尝试让stringSet 急切加载。这没有按预期工作,并且在beforeDelete 代码中它通常是单个值或空白。

我还尝试将 StringSet 设为 Set,在其中我定义了一个包含该值的 GORM 对象 MyString。这确实有效(尽管我不得不急切地获取它),但我认为这不是您的案例的有效解决方案,因为我假设您已经拥有数据并且不能只是替换它。

基于一些调试挖掘,我猜测(但实际上只是猜测)集合在beforeDelete 事件触发之前被删除,因此即使在新交易。我希望其他人可以权衡这是否正确,但如今 grails 2 专业知识越来越难找到。

【讨论】:

  • 是的,我在 slack 频道上得到的答案是尝试使用 Eager fetch。我尝试使用lazy: false 打开它,这似乎在这个简单的示例中有效。希望尽快在生产代码上试用。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-01
  • 1970-01-01
相关资源
最近更新 更多