2015-09-29 2 views
1

У меня есть наследие базы данных и некоторые таблицы имеют составные идентификаторыГорм и составные ключи в ассоциациях

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

Я хочу, чтобы удалить запись из Горм ассоциации:

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 и генерирует запрос к delete with clientId = null, поскольку клиент является частью составного ключа

Какое наилучшее решение в этом случае. Похоже, что GORM имеет плохую поддержку составных клавиш или неправильное отображение.

+0

Также модульные тесты GORM показывают странное поведение при настройке выше. Если добавить equals/hashcode в класс настроек, он будет иметь повторяющиеся строки после сохранения строк. –

ответ

0

При использовании hasMany без belongsTo на многие стороны, другими словами однонаправленный ассоциации, вы получаете присоединиться к столу. Например ...

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

class Item { } 

бы дать три таблицы базы данных: purchase_order, пункт и purchase_order_items. Таблица purchase_order_items будет содержать два столбца: purchase_order_id и item_id. Вы можете узнать больше о таблицах соединений here.

Поскольку вы имеете дело с устаревшей базой данных, я думаю, что лучшим решением является не использование addTo*() и removeFrom*().

  1. Убедитесь, что у вас нет таблицы соединений. Если у вас есть таблица соединений, удалите ассоциацию hasMany.
  2. Вам нужно будет добавить/удалить Setting экземпляров вручную.

Пример:

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 ожидает, что он будет ограничен в том, что она может сделать для тебя.

+0

Благодарим за ответ. Но я использую нечто похожее на обходное решение и поддерживаю hasMany. Но это выглядит странно. Я задаюсь вопросом, существует ли правильное решение. У спящего режима есть одна и та же проблема, или это одна из недостающих функций gorm-hibernate. –

+0

Кроме того, в соответствии с журналами hibernate мое сопоставление не использует таблицу соединений вообще –

Смежные вопросы