Grails GORM: How do I create a composite primary key and use it for a table relationship?

删除回忆录丶 提交于 2020-01-11 10:55:25

问题


I have two tables, one of which (legacy table: A) has two fields that should serve as a composite foreign key and the other one (new table: B) should use a composite primary key for a each row:A has one row:B relationship. How do I describe these tables in terms of GORM?

So far I've been able to create a domain class that reflects the legacy table:A

class A {

    ...
    //composite foreign key to link B class
    String className;
    String eventName;

    B b; //instance of B to be related

    static mapping = {
        table 'a_table';            
        id column: 'id';
        className column: 'class_name';
        eventName column: 'event_name';
        //b: ???
    }
}

which works, but I can't create a new class:B and the relationship.

I tried to declare B as:

class B implements Serializable{

    static auditable = true;

    String name;
    String className;
    String eventName;

    static mapping = {
        //supposed to make a composite PK
        id composite:[className, eventName] 
    }
}

but this won't compile with a
ERROR context.GrailsContextLoader - Error executing bootstraps: Error evaluating ORM mappings block for domain [com.package.B]: No such property: eventName for class: org.codehaus.groovy.grails.orm.hibernate.cfg.HibernateMappingBuilder

What I want is something like:

static mapping = {
    ...
    b composite: [b.className:className, b.eventName:eventName]
    //or whatever is the right way for this to be done.
}

for the A class to make GORM handle this relation.


回答1:


Did you try to use attribute name instead of use attribute value ?

class B implements Serializable{
    String name;
    String className;
    String eventName;

    static mapping = {
        //supposed to make a composite PK
        id composite:['className', 'eventName'] 
    }
}

And mapping in A :

class A {
    static hasMany = [ b : B ]
}

No need to have className or eventName in A




回答2:


The B class has to be declared Serializable and implements the equals and hashCode methods

import org.apache.commons.lang.builder.HashCodeBuilder
class B implements Serializable{

    static auditable = true;

    String name;
    String className;
    String eventName;
    boolean equals(other) {
    if (!(other instanceof B)) {
        return false
    }

    other.className == className && other.eventName == eventName
    }

    int hashCode() {
    def builder = new HashCodeBuilder()
    builder.append className
    builder.append eventName
    builder.toHashCode()
    }

    static mapping = {
        //supposed to make a composite PK
        id composite:["className", "eventName"] 
    }
}

and the A class just must to have an attribute of the B class and the GORM make the composite foreign key

class A {

    //composite foreign key to link B class
    B b; //instance of B to be related

    static mapping = {
        table 'a_table';            
        id column: 'id';
    }
}

it create two tables in the database

+--------------------------------------------------+
|                       A_TABLE                    |  
+--------+-----------+--------------+--------------+
|   id   |  version  |  b_className | b_eventName  |
+--------+-----------+--------------+--------------+
--where the Primary key is "id" and the foreign key are "b_className and b_eventName" 
+--------------------------------------------------+
|                       B                          |  
+--------+-----------+--------------+--------------+
|  name  |  version  |  className   | eventName    |
+--------+-----------+--------------+--------------+
--where the Primary key are "className and eventName" 

if you what to change the name of the columns to other just add the clausule in the mapping statement

class A {

    //composite foreign key to link B class
    B b; //instance of B to be related

    static mapping = {
        table 'a_table';            
        id column: 'id';
        columns {
              b {
                 column name: "className"
                 column name: "eventName"
              }
        }
    }
}



回答3:


import org.apache.commons.lang.builder.HashCodeBuilder
class Person implements Serializable {

String firstName
String lastName

boolean equals(other) {
    if (!(other instanceof Person)) {
        return false
    }

    other.firstName == firstName && other.lastName == lastName
}

int hashCode() {
    def builder = new HashCodeBuilder()
    builder.append firstName
    builder.append lastName
    builder.toHashCode()
}

static mapping = {
    id composite: ['firstName', 'lastName']
}
}

this is what you can find from official docs of grails,

http://grails.org/doc/latest/guide/GORM.html#compositePrimaryKeys

just blindly follow this and your problem will be solved. for explanation refer above link



来源:https://stackoverflow.com/questions/14729629/grails-gorm-how-do-i-create-a-composite-primary-key-and-use-it-for-a-table-rela

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!