【问题标题】:Grails 3 beforeInsert() not stopping associated inserts?Grails 3 beforeInsert() 没有停止相关的插入?
【发布时间】:2025-11-25 19:40:01
【问题描述】:

我有一个我认为是简单的 hasMany 关联 - UserGroup hasMany Users,并且 UserGroup 由 User 拥有:

class UserGroup {

    String name
    User owner
    Set members = []
    static hasMany = [members: User]
    ...
}

到目前为止还不错。我希望每个所有者的名称都是唯一的,因此最初对名称进行了限制:

name unique: 'owner'

但是,这也阻止了同名的更新。所以我将约束移到 beforeInsert 并明确执行逻辑:

def beforeInsert() {
    boolean existing = false
    UserGroup.withNewSession {
        existing = UserGroup.where {
            owner == this.owner && name == this.name
        }.count() > 0
    }
    if (existing) {
        this.errors.rejectValue(...)
    }
    return !this.hasErrors()
}

当保存一个带有成员的新 UserGroup 对象时,并且 beforeInsert 传递,我看到休眠操作 a) 插入 UserGroup 然后 b) 插入成员。

当保存带有成员的新 UserGroup 对象时,由于名称重复而 beforeInsert 失败,我只看到插入成员的休眠操作。这当然会失败,因为没有父记录。

我是不是做错了什么,还是 beforeInsert 只是杀死了 save() 操作的一部分,而不是整个操作?又该怎么办?

【问题讨论】:

  • 作为回答,我不应该需要任何特殊代码,因为(正确)发布的更新不会违反唯一性约束。所以问题已经消失了,但是 beforeInsert() 的行为我觉得还是有问题的。
  • 当保存一个带有成员的新用户组对象,并且 beforeInsert 失败due to a duplicate name,这当然会失败,因为有no parent record. ...为什么没有父级?是因为它被 beforeInsert 发现为duplicate,正如您所建议的那样。不确定您当前的问题是否有任何价值。因为即使它确实有它不能因为它是重复的父级,它也必须回滚两个表而不是现在的 1

标签: hibernate grails grails-orm has-many


【解决方案1】:

beforeInsert 上的代码应该在自定义验证器上,但它正在检查唯一名称,因此正确的约束应该只是 name unique: true (不确定 name unique: 'owner' 是做什么的,因为它无效,该值应为布尔值,如规范https://docs.grails.org/latest/guide/validation.html)

如果您希望将组中的用户以级联方式保存,可以在文档https://docs.grails.org/latest/ref/Database%20Mapping/cascade.html中指定的映射字段中指定

如果自定义验证器失败,或者只是唯一失败,则不应执行级联保存/更新。

【讨论】:

    最近更新 更多