Grails 3 beforeInsert() not stopping associated inserts?

313 views Asked by At

I have what I thought was a simple hasMany association - a UserGroup hasMany Users,and the UserGroup is owned by a User:

class UserGroup {

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

Fine so far. I wanted the name to be unique per owner, so originally put a constraint on name:

name unique: 'owner'

However, this also prevented updates of the same name. So I moved the constraint to beforeInsert and execute the logic expicitly:

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()
}

When saving a new UserGroup object with members, and beforeInsert passes, I see the hibernate actions to a) insert the UserGroup then b) insert the members.

When saving a new UserGroup object with members, and beforeInsert fails due to a duplicate name, I see only the hibernate actions to insert the members. This fails of course since there is no parent record.

Am I doing something wrong, or is it true that beforeInsert is only killing part of the save() operation and not the whole thing? And what to do?

1

There are 1 answers

0
Pablo Pazos On

That code on beforeInsert should be on a custom validator, but it is checking for unique name, so the right constraint should be just name unique: true (not sure what name unique: 'owner' does since it is not valid, the value should be boolean as in the specs https://docs.grails.org/latest/guide/validation.html)

And if you want to users in a group to be saved in cascade, that can be specified in the mapping field as specified on the docs https://docs.grails.org/latest/ref/Database%20Mapping/cascade.html

If the custom validator fails, or just the unique fails, the cascade save/update should not be executed.