Grails GORM和关联中的复合键

Grails GORM和关联中的复合键,grails,gorm,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 ccyPairPat

我有遗留数据库,有些表有复合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*将客户机属性设置为null,并生成要删除的查询,clientId=null,因为客户机是复合键的一部分

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

当您在多侧使用hasMany而不使用belongsTo时,即单向关联,您将得到一个联接表。例如

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

class Item { }
将生成三个数据库表:采购订单、项目和采购订单项目。purchase\u order\u items表将包含两列:purchase\u order\u id和item\u id。您可以阅读有关联接表的更多信息

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

  • 确保没有联接表。如果有联接表,请删除hasMany关联
  • 您需要手动添加/删除
    设置
    实例
  • 示例:

    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期望的不一致,那么它为您提供的功能将受到限制。

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

    class PurchaseOrder {
        static hasMany = [items: Item]
    }
    
    class Item { }
    
    将生成三个数据库表:采购订单、项目和采购订单项目。purchase\u order\u items表将包含两列:purchase\u order\u id和item\u id。您可以阅读有关联接表的更多信息

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

  • 确保没有联接表。如果有联接表,请删除hasMany关联
  • 您需要手动添加/删除
    设置
    实例
  • 示例:

    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期望的不一致,那么它对您的帮助将受到限制。

    此外,GORM单元测试在上述设置中显示出奇怪的行为。如果将equals/hashcode添加到Settings类中,那么一旦保存了行,它就会有重复的行。所以GORM单元测试在上面的设置中显示出奇怪的行为。如果将equals/hashcode添加到设置类中,则在保存行后,它将具有重复的行谢谢您的响应。但我使用了类似的解决方法,并保持了许多联系。但这看起来很奇怪。我想知道是否有合适的解决办法。hibernate是否也有同样的问题,或者它是gorm-hibernate缺少的特性之一。此外,根据hibernate日志,我的映射根本不使用联接表。谢谢您的回复。但我使用了类似的解决方法,并保持了许多联系。但这看起来很奇怪。我想知道是否有合适的解决办法。hibernate是否也有同样的问题,或者它是gorm-hibernate缺少的特性之一。此外,根据hibernate日志,我的映射根本不使用联接表