Grails GORM:如何创建复合主键并将其用于表关系?

时间:2013-02-06 12:55:41

标签: grails gorm

我有两个表,其中一个表(遗留表:A)有两个字段应该作为复合外键使用,另一个表(新表:B)应该使用复合主键作为{{1}关系。如何根据GORM描述这些表?

到目前为止,我已经能够创建一个反映旧表的域类:A

each row:A has one row:B

有效,但我无法创建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: ??? } } 和关系。

我试图将B声明为:

new class:B

但是这不会用 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] } }

我想要的是:

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

让A类使GORM处理这种关系。

3 个答案:

答案 0 :(得分:8)

您是否尝试使用属性名称而不是使用属性值?

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

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

在A:

中进行映射
class A {
    static hasMany = [ b : B ]
}

className

中无需eventNameA

答案 1 :(得分:3)

必须将B类声明为Serializable并实现equals和hashCode方法

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"] 
    }
}

并且A类必须具有B类的属性并且GORM才能生成复合外键

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';
    }
}

它在数据库中创建了两个表

+--------------------------------------------------+
|                       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" 

如果要将列的名称更改为其他,只需在映射语句中添加clausule

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"
              }
        }
    }
}

答案 2 :(得分:0)

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']
}
}

这是你可以从官方的grails文档中找到的,

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

只是盲目跟随这一点,你的问题就会得到解决。有关解释,请参阅以上链接