2009-11-12 16 views
5

Grails GORM non mantiene le classi di dominio astratte nel database, causando un'interruzione delle relazioni polimorfiche. Ad esempio:Classi astratte nelle relazioni 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) 
    } 
} 

provoca

provocato da: org.hibernate.MappingException: Un'associazione dal documento tabella si riferisce a una classe mappata: Utente ... 25 more 2009-11- 11 23: 52: 58,933 [main] ERROR mortbay.log - Nidificato in org.springframework.beans.factory.BeanCreationException: errore nella creazione di bean con nome 'messageSource': Inizializzazione di bean fallita; l'eccezione annidata è org.springframework.beans.factory.BeanCreationException: Errore creazione bean con nome 'transactionManager': Impossibile risolvere il riferimento in bean 'sessionFactory' durante l'impostazione della proprietà bean 'sessionFactory'; l'eccezione nidificata è org.springframework.beans.factory.BeanCreationException: Errore creazione di bean con nome 'sessionFactory': Invocazione del metodo init non riuscita; eccezione annidata è org.hibernate.MappingException: Un associazione dal documento tabella si riferisce a una classe mappata: Utente: org.hibernate.MappingException: Un'associazione dal documento tavola si riferisce ad una classe mappata: Utente

Ma in questo scenario, voglio gli effetti polimorfici di consentire a qualsiasi utente di possedere un documento, mentre costringendo ogni utente del sistema a rientrare in uno dei ruoli definiti. Quindi, l'Utente non dovrebbe essere istanziato direttamente e reso astratto.

Non voglio usare un enum per i ruoli in una classe utente non astratta, perché voglio essere in grado di aggiungere proprietà aggiuntive ai diversi ruoli, che potrebbero non avere senso in determinati contesti (I don ' voglio avere un singolo utente con il ruolo impostato su RegularEmployee che ottiene in qualche modo un gruppo gestito non nullo).

Si tratta di un bug in Grails? Mi sto perdendo qualcosa?

+0

Mi chiedo cosa significherebbe per una classe astratta essere mantenuta nel DB, poiché deve esserci qualcosa per persistere (cioè un'istanza). –

+0

Bene, vorrei azzardare che una classe astratta sia la struttura preliminare dello schema, specialmente se è alla base di una relazione di ereditarietà. Quindi, se ho una relazione User-> RegularEmployee, il nome della tabella dovrebbe essere User e dovrebbe essere aggiunta una colonna per "class", che è usata per memorizzare il tipo a la tabella standard per modello di gerarchia. –

risposta

3

Ti potrebbe interessare visualizzare i modelli di dominio per i plugin Shiro, Nimble (utilizza Shiro) e/o Spring Security. Creano un dominio utente concreto e un dominio di ruolo concreto. Shiro in particolare crea un dominio UserRole per la mappatura many-to-many.

Quindi, nel dominio Ruolo, è possibile aggiungere qualsiasi proprietà desiderata. Se necessario, è possibile creare un dominio separato per consentire oggetti arbitrari in questo modo:

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

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

non credo si otterrà quello che stai cercando nella vostra mappatura dominio corrente però.

+0

Grande chiamata sui plug-in Shiro, Nimble e Spring Security (presumo che si tratti di Acegi?). Sto cercando un confronto tra di loro, ma tutto quello che sto trovando sono vecchi messaggi per mailing list da 2K7, che probabilmente hanno un'applicabilità limitata al Grails moderno. Ti capita di sapere di risorse che offrono confronti affini? –

+0

No, non ho mai trovato un confronto completo su tutti loro. Ho usato Shiro prima (come JSecurity), quindi quando Nimble è stato annunciato all'inizio di quest'anno sembrava una mossa naturale (costruita su Shiro con un set di funzionalità molto più grande). Ho sempre visto post su Spring Security (aka Acegi) ma non ne ho mai letto altro. –

2

Stavamo testando l'ereditarietà dell'eredità dei graal l'altro giorno al lavoro per esaminare il polimorfismo. Abbiamo trovato i seguenti scenari:

Superclasse astratta: le sottoclassi ereditano il comportamento del genitore ma il genitore non può essere utilizzato per fare riferimento a una sottoclasse che si desidera archiviare nel database.

Superclasse con tablePerHeirarchy false - Le sottoclassi memorizzano i campi del genitore nella tabella del genitore, il polimorfismo funziona come previsto.

Superclasse vuota con tablePerHeirarchy false - Le sottoclassi archiviano tutti i propri dati nella loro tabella, il polimorfismo funziona come previsto.

Quindi nel tuo caso, se hai fatto dovresti rimuovere la parola chiave abstract dalla classe utente, tutto funzionerebbe come previsto. L'unico lato negativo è che tutti i campi Utente sono memorizzati nella tabella Utente, lasciando la tabella RegularEmployee con solo le colonne id e version e la tabella Manager avendo solo un riferimento a una riga Workgroup.

+0

Interessante, ma la rimozione della parola chiave abstract consentirebbe anche la creazione di istanze degli oggetti Utente. Ciò significa che esiste un modo per creare un utente che non è forzato esplicitamente in uno dei ruoli, il che viola la mia logica aziendale. –

+0

Questo è un buon punto. Suppongo che potresti aggirare questo creando un costruttore esplicito che genera un'eccezione, ma anche in quel caso ciò che vogliamo veramente è una classe astratta. Per chiunque altro legga questo, assicurati di votare per il problema su JIRA. http://jira.codehaus.org/browse/GRAILS-5356 – Blacktiger

Problemi correlati