2011-09-24 15 views
7

Używam Grails i mam model domeny z wieloma relacjach hasMany atrybutów do tej samej klasy domeny, która wygląda następująco:Wiele relacje hasMany do tej samej klasy domeny w Grails

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

problem, że ja Zdarza mi się, że kiedy dodam coś do listy postów, to w jakiś sposób trafi na listy upodobań i antypatii. Przynajmniej tak to wygląda, gdy przeglądam każdą z tych list.

Myślę, że problemem jest to, że ja też mam następującą zależność w mojej domenie Post:

static belongsTo = [ contributer : Contributer ] 

Co jest najlepszym sposobem będzie o konfigurowaniu tych relacji, aby moje prace modelu? Jakieś sugestie?


@Wayne,

Próbowałem za pomocą testu, jak również i przeszedł pomyślnie. Jedyne, co mogę myśleć to to, że coś jest nie tak z moją metodą zapisu w moim kontrolerze PostController. Mam wklejony kod relavent poniżej (używam pluginu Wiosna Bezpieczeństwo Core i moja klasa Contributer rozszerza klasę użytkownika, który jest tworzony z tej wtyczki):

@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]) 
} 
} 

Czy jest coś, co wyróżnia się tutaj?

+0

po dodaniu posta do robicie contributer 'myPost.contributer = myContributer' lub 'myContributer.addToPosts (myPost)'? – fixitagain

+0

@fixitagain, dzięki za odpowiedź. Próbowałem obu sposobów, z tym samym rezultatem. – NickForrer

Odpowiedz

12

Problem polega na tym, że masz jeden do wielu między Post i Contributor (post ma autora, autor ma wiele postów), a także dwie wiele do wielu relacji między Post i Contributor (post ma wiele likers, likers like many posty) (post ma wielu nielubiących, nie lubią wielu postów). belongsTo w Post wyjaśnia zachowanie, ale jego usunięcie nie rozwiąże problemu, wystarczy utworzyć inne. Rezultat końcowy jest taki, że konwencje GORM będą nieskuteczne, więc musisz powiedzieć GORM, jak zachowywać się lub modelować rzeczy w różny sposób.

Istnieje kilka opcji, ale ten, który skacze na myśl to modelować głosów oddzielnie ze stanowiska i zrobić to tak, że specjalista hasMany likeVotes i 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 będzie modelować to jako jeden głos stole z kolumną dyskryminacyjną, aby rozróżnić upodobania i nielubienia; pozwoli to wyeliminować konflikty między polubieniami, antypatiami i autorami postów.

Następnie w specjalista

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

Relacje są zerowane się:

  1. post ma wiele likeVotes
  2. post ma wiele dislikeVotes
  3. Współtwórca posiada wiele likeVotes
  4. specjalista ma wiele nie lubię głosów
  5. Post posiada jeden z moich współpracowników
  6. specjalista ma wiele postów

GORM może zrozumieć te relacje i będzie zachowywać się odpowiednio.

Jeśli ta opcja nie odpowiada, następnym krokiem będzie określenie niestandardowych mapowań dla struktury bazy danych, a następnie użycie mappedBy w celu rozróżnienia różnych zależności. Jest to podejście, które należy podjąć, jeśli chcesz, aby współtwórca odniósł się bezpośrednio do Post na trzy różne sposoby.

+0

Dzięki za odpowiedź! Myślę, że to wyjaśniło wiele zamieszania związanego z GORM. Bardzo informujące! – NickForrer

+0

Naprawdę fajne rozwiązanie +1 – fixitagain

1

Czy możesz pokazać przypadek testowy, który się nie powiódł? Włożyłem co myślę jest sprawa do grails 1.3.7 projektu i testy przechodzi:

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

Proszę zobaczyć edycję na pytanie. Dzięki za odpowiedź. –

1

spróbuj przełączyć się wiele-do-wielu relacji i zdefiniować domenę mapowania klasa. W tej klasie domeny mapowania możesz określić typ relacji; lubić, nie lubić autora.

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

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

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

Możesz zajrzeć tutaj http://www.grails.org/Many-to-Many+Mapping+without+Hibernate+XML celu uzyskania dalszych informacji na wiele-do-wielu klasie domeny mapowanie.

0

powinno to utwory:

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

Stosować statyczny mappedBy w swojej klasie domeny

Na przykład:

w wielu obiektu domeny boczny (Contributer.groovy):

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

W jednym z obiektu domeny bocznej (Post.groovy):

Class Post { 

     static belongsTo = [ contributer : Contributer ] 

     Contributer postsContributer 
     Contributer likesContributer 
     Contributer dislikesContributer 

    ... 
} 
Powiązane problemy