Grails: Legacy DB - Record with composite Id won't update

372 views Asked by At

I'm having problems trying to update a record on a Grails 2.3.7 Project

I don't want to modify the fields that are part of the composite Id, I just want to update the other fields.

Just one class, few properties, but every time I try to update, it throws me the "not unique error" when this lines runs:

personInstance.validate()
if (personInstance.hasErrors()) {
    respond personInstance.errors, view:'create'
    return
}

My class looks like this:

    class Person implements Serializable {

    static constraints = {
        name(unique: lastName)
    }

    static mapping = {
        id generator: 'assigned'
        id composite: ["name", "lastName"]
    }

    //Override equals and hashcode methods
    boolean equals(other) {
    if (!(other instanceof Person)) {
        return false
    }

        other.name == name && other.lastName == lastName
    }
    int hashCode() {
        def builder = new HashCodeBuilder()
        builder.append name
        builder.append lastName
        builder.toHashCode()
    }

    String name
    String lastName
    String description
}

And the controller action:

def update() {
   def personInstance = Person.get(new Person(name:params.name, lastName:params.lastName))
   personInstance.properties = params

   personInstance.validate()
   if (personInstance.hasErrors()) {
      respond personInstance.errors, view:'create'
      return
   }

   personInstance.save flush:true

   request.withFormat {/*etc...*/}

}

When I use validate(), it throws me a Grails unique key error, when I avoid validation its a BD not unique PK error. Is like Grails didn't know if I want to do an insert or an update when I personInstance.validate().

Is there a way to manage this in a correct way that I'm not seeing? Or am I forced to avoid validation? am I doing something wrong?

Thanks in advance.

1

There are 1 answers

1
Andrew On

I believe the GORM mapping DSL expects just one id definition. Try combining your two id lines into just this one:

id generator: 'assigned', composite: ["name", "lastName"]

Also, in addition to implementing Serializable, your domain class should override equals and hashCode, as described under "Composite Primary Keys" here: http://grails.org/doc/latest/guide/single.html#identity