Абстрактные классы в отношениях GORM - PullRequest
5 голосов
/ 12 ноября 2009

Grails GORM не сохраняет абстрактные доменные классы в базе данных, что приводит к разрыву в полиморфных отношениях. Например:

abstract class User {
    String email
    String password
    static constraints = {
        email(blank:false, nullable:false,email:true)
        password(blank:false, password:true)
    }

    static hasMany = [membership:GroupMembership]
}

class RegularEmployee extends User {}

class Manager extends User {
    Workgroup managedGroup
}

class Document {
    String name
    String description
    int fileSize
    String fileExtension
    User owner
    Date creationTime
    Date lastModifiedTime
    DocumentData myData
    boolean isCheckedOut
    enum Sensitivity {LOW,MEDIUM,HIGH}
    def documentImportance = Sensitivity.LOW

    static constraints = {
        name(nullable:false, blank:false)
        description(nullable:false, blank:false)
        fileSize(nullable:false)
        fileExtension(nullable:false)
        owner(nullable:false)
        myData(nullable:false)
    }
}

вызывает

Вызывается: org.hibernate.MappingException: ассоциация из Табличный документ ссылается на несопоставленный класс: пользователь ... еще 25-11-11 23: 52: 58,933 [main] ОШИБКА mortbay.log - Вложена в org.springframework.beans.factory.BeanCreationException: Ошибка при создании компонента с именем 'messageSource': инициализация компонента не удалось; вложенное исключение org.springframework.beans.factory.BeanCreationException: ошибка создание компонента с именемactionManager: не удается разрешить ссылку для bean-компонента sessionFactory при установке свойства bean-компонента sessionFactory; вложенное исключение org.springframework.beans.factory.BeanCreationException: ошибка создание компонента с именем sessionFactory: вызов метода init не удалось; Вложенное исключение - org.hibernate.MappingException: An ассоциация из таблицы документа относится к несопоставленному классу: пользователь: org.hibernate.MappingException: ассоциация из документа таблицы ссылается на несопоставленный класс: пользователь

Но в этом сценарии я хочу, чтобы полиморфный эффект позволял любому пользователю владеть документом, заставляя каждого пользователя системы вписываться в одну из определенных ролей. Следовательно, Пользователь не должен быть непосредственно создан и сделан абстрактным.

Я не хочу использовать перечисление для ролей в неабстрактном классе User, потому что я хочу иметь возможность добавлять дополнительные свойства к различным ролям, что может не иметь смысла в определенных контекстах (я не хочу иметь одного пользователя с ролью RegularEmployee, которая каким-то образом получает ненулевую управляемую группу).

Это ошибка в Grails? Я что-то пропустил?

Ответы [ 2 ]

3 голосов
/ 12 ноября 2009

Вы можете просмотреть модели доменов для плагинов Shiro, Nimble (использует Shiro) и / или Spring Security. Они создают конкретный домен пользователя и конкретный домен роли. В частности, Широ создает домен UserRole для сопоставления «многие ко многим».

Затем в своем Ролевом домене вы можете добавить любые свойства, которые захотите. При необходимости вы можете создать отдельный домен, чтобы учесть произвольные свойства, например:

class Role {
    //some properties
    static hasMany = [roleProperties:RoleProperty, ...]
}

class RoleProperty {
    String name
    String value
    static belongsTo = [role:Role]
}

Я не думаю, что вы получите то, что ищете в текущем сопоставлении доменов.

2 голосов
/ 13 ноября 2009

На днях мы тестировали наследственную наследственность Грааля, чтобы посмотреть на полиморфизм. Мы нашли следующие сценарии:

Абстрактный суперкласс - подклассы наследуют поведение родителя, но родительский объект нельзя использовать для ссылки на подкласс, который вы хотите сохранить в базе данных.

Суперкласс с tablePerHeirarchy false - Подклассы хранят поля родителя в таблице родителя, полиморфизм работает как положено.

Пустой суперкласс с tablePerHeirarchy false - подклассы хранят все свои данные в своей таблице, полиморфизм работает как положено.

Так что в вашем случае, если бы вы удалили абстрактное ключевое слово из класса пользователя, все работало бы так, как ожидалось. Единственным недостатком является то, что все поля User хранятся в таблице User, оставляя таблицу RegularEmployee только со столбцами id и version, а таблица Manager имеет только ссылку на строку рабочей группы.

...