关联中的GORM和复合键

时间:2015-09-29 14:40:39

标签: grails gorm

我有遗留数据库,有些表有复合ID

class Client {
   String id

   static hasMany = [
      settings: Setting
   ]

   static mapping = {
      id column: 'client_id', generator: 'assigned'
   }
}

class Setting {
   Client client
   String nodeId
   String ccyPairPattern
   Character qualifier

   static mapping = {
      id composite: ['client', 'nodeId', 'pattern', 'qualifier']
   }
}     

我想删除GORM协会的条目:

client.get('1').removeFromSettings(settingToRemove)
// settingToRemove.delete(flush: true) 
// delete-orphans does not help

这在刷新后总是引发异常

 org.hibernate.StaleObjectStateException: Row was updated or deleted by      another transaction (or unsaved-value mapping was incorrect) :

这是因为方法removeFrom *将client属性设置为null并生成查询以使用clientId = null删除,因为客户端是复合键的一部分

在这种情况下,最佳解决方案是什么。看起来GORM对复合键的支持很差,或者我的映射不正确。

1 个答案:

答案 0 :(得分:0)

当您在多方使用 hasMany 而没有 belongsTo 时,换句话说就是单向关联,您将获得一个连接表。例如......

class PurchaseOrder {
    static hasMany = [items: Item]
}

class Item { }

将产生三个数据库表: purchase_order item purchase_order_items purchase_order_items 表将包含两列: purchase_order_id item_id 。您可以阅读有关联接表here的更多信息。

由于您正在处理遗留数据库,我认为最佳解决方案是不使用addTo*()removeFrom*()

  1. 确保您没有联接表。如果您有联接表,请删除 hasMany 关联。
  2. 您需要手动添加/删除Setting个实例。
  3. 示例:

    def client = Client.get(1)
    
    // Adding a setting
    def setting = new Setting(client: client, nodeId: blah...)
    setting.save()
    
    // Removing a setting
    
    /*
     The prototype is used to search for a domain instance with a composite primary key.
     So simply set the composite key properties accordingly.
    */
    def prototype = new Setting(client: client, nodeId: blah...)
    def setting = Setting.get(prototype)
    setting.delete()
    

    缺少 hasMany 关联,您无法通过client.settings媒体资源访问客户端设置。相反,您必须像这样查询它们:

    def settings = Setting.findByClient(client)
    

    使用遗留数据库的结果是,如果数据库与GORM / Hibernate不一致,那么它将会受到限制。