2011-09-24 6 views
7

sto usando Grails, e ho un modello di dominio con hasMany più attributi alla stessa classe di dominio, che assomiglia a questo:molteplici relazioni hasMany per stessa classe di dominio in Grails

static hasMany = [ posts : Post, likes : Post, dislikes : Post ] 

Il problema che ho Mi sto imbattendo quando aggiungo qualcosa all'elenco dei post, ma in qualche modo lo inserisce nelle liste Mi piace e Non mi piace. Almeno, è così che appare quando faccio scorrere tutte queste liste.

Penso che il problema è che ho anche la seguente relazione nel mio dominio del messaggio:

static belongsTo = [ contributer : Contributer ] 

Qual è il modo migliore di andare sulla configurazione di questi rapporti per rendere il mio lavoro modello? Eventuali suggerimenti?


@Wayne,

Ho provato ad utilizzare il test pure, ed è superato con successo. Quindi, l'unica cosa che posso pensare è che c'è qualcosa di sbagliato nel mio metodo di salvataggio nel mio PostController. Ho incollato il codice relavent sotto (sto usando il plugin Primavera di sicurezza Core e la mia classe contributore estende la classe User che viene creato con questo plugin):

@Secured(['IS_AUTHENTICATED_FULLY']) 
def save = { 
def props = [title:params.title, post:params.post, category:Category.get(params.category.id)] 

def user = Contributer.get(springSecurityService.principal.id) 
def postInstance = new Post(props) 

postInstance.contributer = user 
if (postInstance.save(flush: true)) { 
    flash.message = "${message(code: 'default.created.message', args: [message(code: 'post.label', default: 'Post'), postInstance.id])}" 
    redirect(action: "show", id: postInstance.id) 
} 
else { 
    render(view: "create", model: [postInstance: postInstance]) 
} 
} 

C'è qualcosa che si distingue qui?

+0

quando si aggiunge un post al contributore cosa fai 'myPost.contributer = myContributer' o 'myContributer.addToPosts (myPost)'? – fixitagain

+0

@fixitagain, grazie per la risposta. Ho provato entrambi i modi, con lo stesso risultato. – NickForrer

risposta

12

Il problema è che si ha uno a uno tra Post e Collaboratore (il post ha un autore, l'autore ha molti post) così come due molti a molti rapporti tra Post e Collaboratore (il post ha molti likers, likers like many post) (post ha molti non graditi, i non gradici non amano molti post). Lo belongsTo in Post spiega il comportamento, ma rimuoverlo non risolverà il problema, ma creane di diversi. Il risultato finale è che le convenzioni GORM stanno per scadere, quindi devi dire a GORM come comportarsi o modellare le cose in modo diverso.

Ci sono diverse opzioni, ma quello che salta alla mente è quello di modellare Votate separatamente dal Post e fare in modo che un collaboratore di hasMany likeVotes e hasMany dislikeVotes

class Vote { 

    // for illustration here, you need to think about the 
    // cascading behavior that makes sense and model it if you decide 
    // to go this route. 
    belongsTo = [post, contributor] 

} 

class LikeVote extends Vote { 
} 

class DislikeVote extends Vote { 
} 

GORM modellerà questo come tavolo di un voto con una colonna discriminante per separare le Mi piace e le Non mi piace; questo ti permetterà di eliminare i conflitti tra Mi piace, Non mi piace e Post creati.

Poi, nel collaboratore

hasMany = [likes:LikeVote, dislikes:DislikeVote, posts:Post] 

Le relazioni sono chiarito subito:

  1. post è molti likeVotes
  2. Post dispone di molte dislikeVotes
  3. collaboratore ha molti likeVotes
  4. collaboratore ha molte antipatiaVoti
  5. Post dispone di un collaboratore
  6. collaboratore ha molti messaggi

GORM può capire queste relazioni e dovrà comportarsi in modo appropriato.

Se non ti piace questa opzione, il passaggio successivo sarebbe quello di specificare i mapping personalizzati per la struttura del database e quindi utilizzare mappedBy per differenziare le varie relazioni. Questo è l'approccio da adottare se si desidera assolutamente che un collaboratore sia direttamente correlato a Post in tre modi diversi.

+0

Grazie per la risposta! Penso che questo abbia chiarito un sacco di confusione riguardo a GORM. Molto informativo! – NickForrer

+0

soluzione davvero interessante +1 – fixitagain

1

Puoi mostrare il test che fallisce? Ho messo quello che penso è il vostro caso in un progetto 1.3.7 graal, e il test viene superato:

class Post { 
    String text ="postal" 
    static belongsTo = [ contributor : Contributor ] 
    static constraints = { } 
} 
class Contributor { 
    String name = "Big C" 
    static hasMany = [ posts : Post, likes : Post, dislikes : Post ] 
    static constraints = { } 
} 

// integration test 
void testMultipleRel() { 
    Contributor c = new Contributor().save() 
    assertNotNull c 

    Post p1 = new Post(text:"neutral") 
    Post p2 = new Post(text:"like") 
    Post p3 = new Post(text:"dislike") 
    [p1,p2,p3].each {c.addToPosts(it).save()} 
    assertNotNull p1 
    assertNotNull p2 
    assertNotNull p3 

    assertNull c.likes 
    assertNull c.dislikes 

    c.addToLikes(p2) 
    c.addToDislikes(p3) 

    assertEquals ([p1, p2, p3] as Set, c.posts as Set) 
    assertEquals ([p2]   as Set, c.likes as Set) 
    assertEquals ([p3]   as Set, c.dislikes as Set) 

}

+0

Si prega di consultare la modifica alla domanda. Grazie per aver risposto. –

1

provare a passare a una relazione molti-a-molti e definiscono un dominio mappatura classe. In questa classe di dominio di mappatura è possibile specificare il tipo di relazione; come, non mi piace, o autore.

class Contributor { 
    static hasMany = [contributorPosts:ContributorPost] 
} 

class ContributorPost { 
    Post post 
    Contributor contributor 
    Boolean like 
    Boolean dislike 
    Boolean author 
} 

class Post { 
    static hasMany = [contributorPosts:ContributorPost] 
} 

Potete guardare qui http://www.grails.org/Many-to-Many+Mapping+without+Hibernate+XML per ulteriori informazioni su una relazione molti-a-molti di classe dominio mappatura.

2

Tuttavia, il modo standard per multi-M: M è di utilizzare joinTable, come raccomandato in GRAILS-4884.

0

questo dovrebbe opere:

static hasMany = [ posts : Post, likes : Post, dislikes : Post ] 

static mapping = { 
    posts joinTable: [name: 'contributor_posts'] 
    likes joinTable: [name: 'contributor_likes'] 
    dislikes joinTable: [name: 'contributor_dislikes'] 
} 
5

Utilizzare statica mappedBy nella classe dominio

Ad esempio:

In molti oggetto di dominio lato (Contributer.groovy):

static hasMany = [ posts : Post, likes : Post, dislikes : Post ] 
static mappedBy = [posts: "postsContributer", likes: "likesContributer", dislikes: "dislikesContributer"] 

In un oggetto di dominio lato (Post.groovy):

Class Post { 

     static belongsTo = [ contributer : Contributer ] 

     Contributer postsContributer 
     Contributer likesContributer 
     Contributer dislikesContributer 

    ... 
} 
Problemi correlati