Grails中的一对一映射

时间:2009-09-28 21:45:09

标签: grails

有人可以帮我弄清楚如何在grails中创建简单的一对一映射的域类!

假设我们有2个表(oracle):

create table table_a(long_common_id_name number(5) primary key using index, 
                     notes varchar2(10 byte), 
                     update_seq number(3)not null );

create table table_b (long_common_id_name number(5) primary key using index, 
                      extra_notes varchar2(200 byte), 
                      update_seq number(3) not null);

alter table table_b add (constraint table_b_fk foreign key (long_common_id_name)
references table_a (long_common_id_name));

我创建了2个域类:

class TableA {
    static mapping = {
        table 'table_a'
        columns {
            id                  column:'LONG_COMMON_ID_NAME'
            data                column:'NOTES'
            version             column:'UPDATE_SEQ'
        }
    }
    String data
    TableB extraData
}

class TableB {
    static mapping = {
        table 'table_b'
        columns {
            id                  column:'LONG_COMMON_ID_NAME'
            data                column:'EXTRA_NOTES'
            version             column:'UPDATE_SEQ'
        }
    }
    String data
}

这个特定的定义是不正确的。 Grails(或Hibernate)为TableA构建了一个不正确的SQL:

select this_.LONG_COMMON_ID_NAME as LONG1_66_0_, this_.UPDATE_SEQ as UPDATE2_66_0_, this_.NOTES as NOTES66_0_, this_.extra_data_id as extra4_66_0_ from table_a this_

我尝试了很多东西:从属,拥有独特的玛尼,但似乎没什么用。

提前致谢。

3 个答案:

答案 0 :(得分:1)

回答我自己的问题,也许有人会发现它很有用......

我正在为我们的旧数据库编写一个快速的web-ui,因此我没有编写大量的SQL来回答用户问题,而是希望将其自动化。我无法修改数据结构,通过UI访问将是只读的。

以下是我可以使用的解决方案/解决方法:

域/ TableA.groovy

class TableA {
    static mapping = {
        table 'table_a'
        columns {
            id                  column:'LONG_COMMON_ID_NAME'
            data                column:'NOTES'
            version             column:'UPDATE_SEQ'
        }
    }    
    // will manually handle persistence of TableB
    static transients = [ 'extraData' ]

    String data
    TableB extraData
}

域/ TableB.groovy

class TableB {
    static mapping = {
        table 'table_b'
        columns {
            id                  column:'LONG_COMMON_ID_NAME'
            data                column:'EXTRA_NOTES'
            version             column:'UPDATE_SEQ'
        }

        //actual id is copied from TableA after it is persisted
        id generator:'assigned'
    }

    static transients = [ "parent" ]

    String data
    TableA parent
}

“views / tableA / create.gsp”中的表单包含TableA和TableB属性的输入字段,因此我将获取TableA和TableB实例的数据


在“controllers / TableAController.groovy”中我手动更新/删除/加载TableB实例

def list = {    
   ...
   def rv = TableA.list( params)
   rv.each() { it.extraData = TableB.get(String.valueOf(it.id)) }
   ...
}

def show = {
   ....
   tableAInstance.extraData = TableB.get(tableAInstance.id)
   ...
}
def delete = {
   ...
   // delete tableB instance first before tableA
   def tb = TableB.get(tableAInstance.id)
   if (tb) tb.delete()

   tableAInstance.delete()
   ...
}

def save = {
   ....
   // after tableAInstance.save() call
   def tb = new TableB()
   tb.data = params.extraData?.data
   // copy id from tableA instance
   tb.id = tableAInstance.id
   tb.save()
   .....
}

答案 1 :(得分:0)

你必须以这种方式设置外键吗?我希望在TABLE_A上有一个TABLE_B_ID列。

无论如何,我认为要做你想要的,你需要为extraData的映射闭包添加一行。

我不确定这是否会很好地将它作为主键

e.g。

 static mapping = {
    extraData column:'LONG_COMMON_ID_NAME'
}

答案 2 :(得分:0)

同意leebuts,Grails将在子表中预期单独的FK ID字段。

此表设置看起来更像是每类表继承。您可以创建一个继承类TableA的类TableB,其中TableA包含Notes,TableB包含“data”。 Grails可能还需要TableB中的一个鉴别器列,但看起来这些表看起来符合Grails惯例的继承。

看看:http://grails.org/GORM+-+Mapping+DSL

寻找关闭每个层次表的方法