1

So I'm attempting to let 2 domains inherit from a single domain.

abstract class Pet {
    Nose nose
    static hasMany = [legs: Leg]
}

class Dog extends Pet {
    static hasMany = [friends: Friend]
}

And I'm getting an error:

Caused by: org.codehaus.groovy.grails.exceptions.InvalidPropertyException: No property found for name [legs] for class [class animals.Dog]

Any ideas? Is there something I have to do to combine the hasManys?

James Kleeh
  • 12,094
  • 5
  • 34
  • 61

2 Answers2

0

I tried replicating the problem and I did not get an InvalidPropertyException, but the database schema that was generated was missing the 1:m relationship between Dog and Leg.

I believe the problem is related to Pet being an abstract class. If the Dog class inherits Set legs from Pet, then in order to persist the Leg instances to the database, the underlying Leg table needs to have a foreign key of pet_id**. Since Pet is an abstract class, a table is not created for it and therefore no id column. Therefore, no foreign key can be created in the dependent class, Leg.

Making the Pet class a concrete class (moving it to grails-app/domain and removing the abstract keyword), means that a table with an id field will be created. And in the Leg table, a pet_id column can/will be created that Hibernate will use to persist/retrieve the Set legs.

** (or an associative entity table, such as pet_legs, would need to have the foreign key)

Making the Pet class concrete, however, will cause all the sub-classes of Pet to be stored into that table, so if you want each sub-class to have its own table, you could add:

  static mapping = {
    tablePerHierarchy false
  }

to the Dog class, which will create a Pet, Dog, etc table in the db.

dspies
  • 1,545
  • 14
  • 19
  • I never wanted a `pet_id` field to use as a foreign key, I just want the properties of Pet to be inherited by `Dog`. – James Kleeh Sep 27 '13 at 18:37
  • Sorry, my original answer may have been a bit cryptic, so I expanded on it to explain what I meant by the `pet_id` issue. – dspies Sep 27 '13 at 20:38
0

You're missing a couple of things:

  1. GORM won't generate table relationships for an abstract class
  2. static fields/methods are not inherited. They belong to the class, not to the object references

So you have to change the code to one of the following:

abstract class Pet {
    Nose nose
}

class Dog extends Pet {
    static hasMany = [legs: Leg, friends: Friend]
}

or

abstract class Pet {
    Nose nose
    static hasMany = [legs: Leg]
}

class Dog extends Pet {
    static hasMany = [friends: Friend] + Pet.hasMany
}

Yes the second approach works because you can initialize static members of a class by another static classe's static member.

Community
  • 1
  • 1
Alexander Suraphel
  • 10,103
  • 10
  • 55
  • 90