2013-04-16 12 views
5

Sto cercando di implementare due diversi tipi di relazioni tra due classi di dominio in Grails.Grails: più relazioni tra due oggetti dominio

Considerare quanto segue; Ho due classi di dominio, una classe autore e libro con un autore che ha molti libri.

class Author{   
    String name 
} 

class Book{ 
    String title 
    static belongsTo = [author:Author] 

} 

Quanto sopra rappresenta una relazione molto basilare con molti tra un autore e un libro. Ma voglio anche che un autore abbia un concetto di un elenco di libri preferiti. Ciò sarebbe idealmente rappresentato come una relazione separata a molte che descrive lo stesso oggetto Book come una lista e persistente come tale.

class Author{   
    String name 
    static hasMany = [favouriteBooks: Book] 

    static mapping = { 
     favouriteBooks joinTable: [name: 'favourite_books', 
       key: 'author_id'] 
    } 
} 

class Book{ 
    String title 
    static belongsTo = [client:Client] 

} 

Ho provato a descrivere come sopra (tra molti altri metodi) e, infine, la tabella del database (favourite_books) non viene creato. Non ho errori. Questo è l'unico modo in cui posso pensare di farlo senza utilizzare oggetti aggiuntivi che vorrei evitare per mantenere il modello semplice. Sento di essere sulla strada giusta ma forse mi manca un pezzo fondamentale del puzzle.

Qualsiasi aiuto sarebbe molto apprezzato.

+0

Hai provato a ** pulita, uscita, graal ** di nuovo, poi ** eseguire-app **. A volte Grails non rileva le modifiche al tuo dominio senza un 'clean' – ikumen

+0

Nel primo esempio in alto ti manca la proprietà' hasMany' sul lato 'Autore' e nel secondo esempio non c'è alcun riferimento alla relazione' favouriteBooks' su il lato 'Book'. –

risposta

2

finalmente capito questo fuori. Grazie a Don per avermi indirizzato verso il plugin db-reverse-engineer che ha permesso di esporre la proprietà chiave che consente questa strategia di mappatura. Fondamentalmente tutto si riduceva all'utilizzo dell'associazione mappedBy di GORM per dire esplicitamente a Grails come devono essere mappati più riferimenti. I file di classe che hanno lavorato sono i seguenti:

class Author { 

    String name 
    static hasMany = [books: Book, favourites: Book] 

    // need to disambiguate the multiple hasMany references with the 
    // 'mappedBy' property: 
    static mappedBy = [books: "author", 
         favourites: "authors"] 
} 

class Book { 

    String title 
    Author author 

    static hasMany = [authors: Author] 
    static belongsTo = [Author] 
} 

Grazie ancora per l'aiuto

1

Modifica classe dominio Book. Rimuovere la mappatura author.

class Book{ 
    String title 
    static belongsTo = [Author] 
} 

Cercare la nuova tabella libri_preferiti volta clean e run-app.

4

Prima di tutto, assicuriamoci di aver compreso correttamente il problema. Hai Book e Author classi di dominio, ma ci sono due relazioni tra queste classi:

  1. Un autore scrive libri, quindi non c'è una relazione uno-a-molti tra Author e Book. Naturalmente nella vita reale un libro può essere scritto da molti autori, ma sembra in questo caso che possiamo ignorarlo.
  2. Un autore ha libri preferiti, quindi c'è una seconda relazione molti-a-molti tra Author e Book. Questa relazione è molti-a-molti perché un particolare libro potrebbe essere uno dei preferiti di molti autori.

Supponendo di aver compreso correttamente il problema, proviamo a trovare una soluzione. Prima di tutto, aggiungiamo i molti-a-molti (libri preferiti):

class Author { 
    String name 
    static hasMany = [favourites: Book] 
} 

class Book { 
    String title 
    static hasMany = [favouritedBy: Author] 
    static belongsTo = Author 
} 

Ogni volta che una relazione molti-a-molti è definito dobbiamo scegliere un lato come essere il proprietario del rapporto. In questo caso ho specificato

static belongsTo = Author 

nella classe Book, così Book è il lato di proprietà del rapporto e Author è il proprietario. Per questo motivo dovremmo aggiungere libri preferiti agli autori piuttosto che viceversa, see here per ulteriori dettagli.

La relazione uno-a-molti può quindi essere aggiunti con:

class Author { 
    String name 
    static hasMany = [favourites: Book, booksWritten: Book] 
} 

class Book { 
    String title 
    static hasMany = [favouritedBy: Author] 
    static belongsTo = Author 

    Book writtenBy 
} 

Tra l'altro, nel modello di dominio è stato incluso il seguente nella classe Author

static mapping = { 
    favouriteBooks joinTable: [name: 'favourite_books', key: 'author_id'] 
} 

Ciò causerà la tabella di join deve essere denominata invece favourite_books, mentre nel mio modello la tabella di join verrà impostata su author_favourites. Se per qualche motivo desideri particolarmente che la tabella di join sia denominata in questo modo (ad esempio stai cercando di associare le classi alle tabelle esistenti), sentiti libero di includere quanto sopra.

Infine, se vi trovate alle prese con la definizione di mappature di classe del dominio, e sono più a suo agio con la creazione delle tabelle, quindi la generazione delle classi di dominio da loro, prova anche this plugin

+0

Grazie per la risposta rapida e dettagliata. Hai ragione nella tua interpretazione di ciò che sto cercando di ottenere e mentre funziona, mi sembra di avere un piccolo problema con questo approccio. Mi sembra di finire con una tabella author_books_written separata per mappare la proprietà di un autore di un libro. Speravo di avere semplicemente un author_id nella mia tabella Libri? È possibile aggirare questo? – dre

+0

A proposito, possiamo ipotizzare che un libro possa avere un solo autore. – dre

Problemi correlati