1

I'm trying to map existing tables in a GORM/Grails app. Most of the tables have composite primary keys (not my choice).

I'm finding that when I map an association to a class (parent of a child) where the composite key of the parent class contains an association to a class with a composite key also (grandparent), GORM doesn't bother to check the mapping of the grandparent class and subs in a non-composite key.

Child

class Child implements Serializable {
    Parent parent
    String name

    belongsTo= [parent: Parent]

    static mapping= {
        id(composite: ['parent', 'name'])
    }
}

Parent

class Parent implements Serializable {
    GrandParent grandParent
    String name
    Collection<Child> children

    belongsTo= [grandParent: GrandParent]
    hasMany= [children: Child]

    static mapping= {
        id(composite: ['grandParent', 'name'])
    }
}

GrandParent

class GrandParent implements Serializable {
    String name
    Integer luckyNumber
    Collection<Parent> parents

    hasMany= [parents: Parent]

    static mapping= {
        id(composite: ['name', 'luckyNumber'])
    }
}

The DDL generation fails when trying to glean the foreign keys.

org.hibernate.MappingException:
Foreign key (FK_1:CHILD [parent_grandparent_id,parent_name]))
    must have same number of columns as the referenced primary key
(PARENT [parent_grandparent_name,parent_grandparent_lucky_number,parent_name])

The foreign key it's created does not match the primary key of the parent class (which it was able to decipher correctly).

U47
  • 193
  • 14
  • it might be connected to the type erasure, and the fact that you are defining some connection multiple times. – shaydel Feb 23 '16 at 12:54

2 Answers2

0

try:

Child

class Child implements Serializable {

    String name

    static belongsTo= [parent: Parent]

    static mapping= {
        id(composite: ['parent', 'name'])
    }
}

Parent

class Parent implements Serializable {
    String name

    //static belongsTo= [parent: Parent]  //why do you need this
    static belongsTo= [GrandParent  ]  //did you mean this
    static hasMany= [children: Child,grandParent: GrandParent  ]

    static mapping= {
        id(composite: ['grandParent', 'name'])
    }
}

GrandParent

class GrandParent implements Serializable {
    String name
    Integer luckyNumber

    static hasMany= [parents: Parent]

    static mapping= {
        id(composite: ['name', 'luckyNumber'])
    }
}
shaydel
  • 589
  • 4
  • 15
  • Yes, I fixed the typo. There's nothing wrong with being verbose on your objects. In fact, it's the only way to define what you want your collections to be, which affects Hibernate's colleciton mapping (bag, list, etc.) – U47 Feb 23 '16 at 15:57
  • Just for the record, removing the definitions of the associations had no effect. The foreign key is still generated incorrectly for the Child domain. – U47 Feb 23 '16 at 16:16
0

I've asked around on Grails Slack #gorm, and this appears to hit a gap in Gorm mapping.

I've raised an issue in the Grails data mapping project. We'll see where this goes.

U47
  • 193
  • 14