2016-04-01 5 views
0

У меня есть два класса домена CGroup и Directory, я хотел бы моделировать CGroup, у которой много каталогов, однако один из этих многих каталогов известен как «корень» и напрямую доступный из CGroup. Любая CGroup должна иметь только один корень., И каскады все равно должны работать так, что удаление любой директории удаляет все ее дочерние элементы.Прямой доступ GORM к экземпляру в hasMany отношениях

Хотя неправильно, это то, что я до сих пор:

class CGroup{ 
    ... 
    Directory root 

    static hasMany = [directory:Directory] 

    static constraints = { 
     root(unique:true) 
    } 
} 

class Directory { 

    static hasMany = [children:Directory] 
    ... 
    static belongsTo = [parent:Directory, 
         cgroup:CGroup] 

    static constraints = { 
     parent nullable: true 
    } 
} 

в основном, я просто нужна ссылка на один экземпляр из «многих» коллекции, хранящейся в «одной» стороне

ответ

1

Я попробовал это несколькими разными способами, и единственный способ заставить его работать - разрешить root быть временно обнуляемым. Проблема, которая у меня была без этого, связана с заказом - поскольку Directory экземпляров находятся в hasMany, они не могут быть сохранены до тех пор, пока не будет сохранен CGroup или вызов save() не будет выполнен, так как cgroup имеет значение null (это установлено при вызове addToDirectory). Но вы не можете сохранить CGroup без установки его свойства root, если он не может быть недействителен.

Так что я сделал root обнуляемого но добавил пользовательский валидатор, который не проходит проверку, если root является недействительным и есть какие-либо экземпляры в hasMany:

static constraints = { 
    root nullable: true, validator: { Directory root, CGroup cgroup -> 
     if (!root && cgroup.directory?.size()) { 
     return ['root.required'] 
     } 
    } 
} 

Таким образом, вы бы сохранить экземпляр CGroup с любыми требуемыми значениями и без любые связанные Directory экземпляры. Затем приложите Directory экземпляры с addToDirectory и установить экземпляр root с пользовательской сеттер:

void setRoot(Directory root) { 
    if (this.root) { 
     removeFromDirectory this.root 
    } 

    if (root) { 
     addToDirectory root 
    } 

    this.root = root 
} 

и сохранить его снова:

def group = new CGroup(...).save() 

group.root = new Directory(...) 
group.addToDirectory(new Directory(...)) 
group.addToDirectory(new Directory(...)) 
group.save() 

g1.errors 
+0

Да! это именно то, что я искал, проблема заказа, которую вы заявили, была точной проблемой, с которой я столкнулся, но я не был так хорошо знаком с пользовательскими валидаторами. Кроме того, я думал, что, возможно, упустил что-то очевидное, поскольку это показалось довольно распространенным сценарием. Одна вещь, в вашем последнем блоке кода не должен быть второй addToDirectory, который действительно является вызовом setRoot? Cheers – Alexjjsmith

+1

Нет, сначала устанавливается корень, а затем добавляются два дополнительных экземпляра в общей сложности 3. Порядок там не имеет значения, если при вызове save() второй раз устанавливается root, и этот экземпляр находится в hasMany, необязательно вместе с некоторыми дополнительными экземплярами. –