0

I'm pretty much certain I'm doing something wrong since this obviously works. Simplified classes:

class Person {
  String name
  static hasMany = [cats:Cat]
}

class Cat {
  String name
  Person person
  static belongsTo = Person
  static constraints = {
    person(nullable:false)
  }
  String toString() {
    "${person.name}-${name}"
  }
}

Simple stuff, a person has many cats, cats must belong to only a single person.

Now when I do the following in a Service class, I get strange results:

delete(Cat cat) {
  Person owner = cat.person
  log.debug("Cats before removing ${cat} (id=${cat.id}): ${owner.cats} -- ${owner.cats*.id}")
  owner.removeFromCats(cat);
  log.debug("Removed from owner ${owner}, owner now has ${owner.cats} -- ${owner.cats*.id}")
  log.debug("Cat to delete is now: ${cat} and belongs to...  ${cat.person}")
  cat.delete(flush:true)
}

And the error is "object would be resaved, blah blah"

org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations)

The weird bit is the debug results, when called to remove cat "Fluffy" who's owned by "Bob":

Cats before removing Bob-Fluffy (id=1356): [Bob-Fluffy] -- [1356]
Removed from owner Bob, owner now has [null-Fluffy] -- [1356]
Cat to delete is now: null-Fluffy and belongs to...  null

What's going on that "removeFrom" isn't actually removing the object from the collection? I cleaned and recompiled. Pretty much at a loss as to why I can't delete this object.

Trebla
  • 1,164
  • 1
  • 13
  • 28

3 Answers3

0

I would try to remove the field person as Person person and leave only the belongsTo field like this

class Cat {
  String name
  static belongsTo = [person:Person]
  static constraints = {
    person(nullable:false)
  }
  String toString() {
    "${person.name}-${name}"
  }
}
Fran García
  • 2,011
  • 16
  • 24
0

It looks like what was happening in my case is that cat.person has getting stale somehow, even though it's the first thing in the method. Calling cat.refresh() didn't work, but calling owner.refresh() after extracting it from the cat.

Trebla
  • 1,164
  • 1
  • 13
  • 28
0

I would change the domain class as such.

class Person {
  String name
  static hasMany = [cats:Cat]
}

class Cat {
  String name
  Person person
  // no need to add belongs to property here. it creates a join table that you may not need
  static constraints = {
  person(nullable:false)
}

String toString() {
    "${person.name}-${name}"
   }
}

In the service class

delete(Cat cat) {
  cat.delete(flush:true)
}

Once you make the domain changes, start with a fresh database since the schema will change.

I think that should solve your problem.

elixir
  • 1,394
  • 1
  • 11
  • 21
  • I definitely need the join table... the cat/person paradigm is silly, but it simplifies the model for example. The Cat can't exist unless it's part of the Person (or rather, makes no sense when not part of the person). It is also not possible to start with a fresh database as this is production code with several years of data. – Trebla Oct 12 '16 at 13:30