簡體   English   中英

Grails的繼承以及一對多和多對多關系的沖突

[英]Grails inheritance and conflicting one-to-many and many-to-many relationship

我通過嘗試創建簡單的Twitter副本來學習grails。 我目前正在嘗試納入關注者和群組。 我最初想出了一個非常基本的數據庫結構,但在實現它方面卻沒有運氣。 關系的設計如下:

    Person:
        has many: Groups, Tweets, (Person as followers through User2Person)
    Group:
        has many: (Person as followers through User2Person)
        belongs to: Person as owner
    User2Person:
        belongs to: (Person or Group)
        belongs to: Person

基本上,我希望Person和Group成為User的實例,然后創建一個將User映射到Person的表。 這樣,僅一個表被創建/用於Group2Person和Person2Person之間的關系。

詳細信息:組是由人員創建的,因此它應該具有“所有者”(person_id)。 它還有許多關注者(即成員)。 組不能跟隨其他組,但是一個人可以跟隨另一個人或一個組。

下面是我如何在grails中實現此功能:

用戶

    abstract class User {
        static hasMany = [followers: Person]
        static mappedBy = [followers: "followed"]
        String name
        Date dateCreated
        Date lastUpdated

        static constraints = {
            name shared: "mustFill", size: 3..20
        }
    }

    class Person extends User {
        static belongsTo = [followed: User]
        static hasMany = [tweets: Tweet, groups: Group]
        static mappedBy = [groups: "owner"]
        String username
        String email

        static constraints = {
            username shared: "mustFill", unique: true, size: 4..15
            email shared: "mustFill", email: true
        }

        static mapping = {
            tweets sort: 'dateCreated', order: 'desc'
        }

    }

    class Group extends User {
        Person owner
        String description

        def getTweets() {
            return followers.tweets.flatten()
        }

        static transients = {
            tweets
        }
    }

鳴叫 (以防萬一?)

    class Tweet {
        static belongsTo = [author: Person]
        String text
        Date dateCreated

        static constraints = {
            text shared: "mustFill", maxSize: 140
        }
    }

當我運行cmd grails schema-export ,出現以下錯誤:“ |錯誤加載插件管理器時出錯:域類[tweeter.Group]和[tweeter.Person類]不能多對多擁有關系。兩者都包含相互引用的belongsTo定義。(使用--stacktrace查看完整的跟蹤)”

我能夠使數據庫創建幾乎正確的架構。 不幸的是,使用了User2Person(又名追隨者)聯接表的主鍵(user_id,person_id)。 那意味着我不能有兩個記錄,例如:(1、2)和(2、1)(例如,兩個用戶彼此關注)。 下面是更新的類( commit ):

用戶

    class User {
        static belongsTo = Person
        static hasMany = [followers: Person]
        String name
        Date dateCreated
        Date lastUpdated

        static constraints = {
            name shared: "mustFill", size: 3..20
        }
    }

    class Person extends User {
        static hasMany = [tweets: Tweet, groups: Group, follows: User]
        static mappedBy = [tweets: "author", groups: "owner"]
        String username
        String email

        static constraints = {
            username shared: "mustFill", unique: true, size: 4..15
            email shared: "mustFill", email: true
        }

        static mapping = {
            tweets sort: 'dateCreated', order: 'desc'
        }

    }

模式中的關注者表如下所示:

    create table user_follows (
        user_id bigint,
        follows__id bigint,
        primary_key(user_id, follows__id)
    )

我在網上搜索了有關更改聯接表主鍵的信息。 我能找到的最好的方法是使用類似以下的代碼:

    static mappedBy = { followers joinTable: [name:"someName", ...] }

不幸的是,我很難找到有關joinTable映射的良好文檔,並且大多數資料似乎都表明不可能輕易更改連接表的主鍵。 然后,我決定按照本指南使用單獨的域類來定義聯接表:沒有Hibernate XML的多對多映射。 以下是最終更新的代碼( commit ):

用戶

    class User {
        static belongsTo = Person
        static hasMany = [people: UserFollower]
        static mappedBy = [people: "followed"]
        String name
        Date dateCreated
        Date lastUpdated

        static constraints = {
            name shared: "mustFill", size: 3..20
        }

        static transients = {
            followers
        }

        def getFollowers() {
            return people.collect { it.follower }
        }

        void addToFollowers(Person person) {
            UserFollower.link(this, person)
        }

        void removeFromFollowers(Person person) {
            UserFollower.unlink(this, person)
        }
    }

    class Person extends User {
        static hasMany = [tweets: Tweet, groups: Group, users: UserFollower]
        static mappedBy = [tweets: "author", groups: "owner", users:"follower"]
        String username
        String email

        static constraints = {
            username shared: "mustFill", unique: true, size: 4..15
            email shared: "mustFill", email: true
        }

        static mapping = {
            tweets sort: 'dateCreated', order: 'desc'
        }

        static transients = {
            follows
        }

        def getFollows() {
            return users.collect { it.followed }
        }

        void addToFollows(User user) {
            UserFollower.link(user, this)
        }

        void removeFromFollows(User user) {
            UserFollower.unlink(user, this)
        }

    }

UserFollower

    class UserFollower {
        User followed
        Person follower

        static constraints = {
            followed nullable: false
            follower nullable: false
        }

        static void link(User user, Person person) {
            UserFollower f = UserFollower.findByFollowedAndFollower(user, person)
            if(!f) {
                f = new UserFollower()
                user.addToPeople(f)
                person.addToUsers(f)
                f.save()
            }
        }

        static void unlink(User user, Person person) {
            UserFollower f = UserFollower.findByFollowedAndFollower(user, person)
            if(f) {
                f = new UserFollower()
                user.removeFromPeople(f)
                person.removeFromUsers(f)
                f.delete()
            }
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM