【问题标题】:Dynamic finders with Grails many-to-many relationship具有 Grails 多对多关系的动态查找器
【发布时间】:2011-07-01 08:47:29
【问题描述】:

我有 2 个域类,它们通过多对多关系映射。我按照 Grails 文档的说明进行操作,但是在处理这些域上的数据时仍然遇到一些问题。这是我的 2 个域类:

class User {
    String name
    int age
    String job
    static hasMany = [groups : Group]
    static belongsTo = [org : Organization]
}

class Group {
    String groupName
    String code
    static hasMany = [members : User]
}

我的问题是:
1.上述关系需要一个类持有belongsTo是关系的“所有者”。在这种情况下,User属于Group,但我不知道如何将belongsTo放到User类中,因为Grails建议的标准语法是static belongsTo = [Group](只需指定所有者类名),所以我不能:
- 像这样将其放入存在的 belongsTo 中: static belongsTo = [org : Organization, Group]
- 或者像这样定义另一个 belongsTo:static belongsTo = [Group]

  1. 下面的例子是正确的:

    课本{ 字符串标题 静态的 belongsTo = 作者 静态 hasMany = [作者:作者]

    static mapping = {
        authors joinTable:[name:"mm_author_books", key:'mm_book_id' ]
    }
    

    } 类作者{ 字符串名称 静态 hasMany = [书籍:书籍]

    static mapping = {
        books joinTable:[name:"mm_author_books", key:'mm_author_id']
    }
    

    }

(参考链接:Many-to-Many link tables in grails (GORM) / hibernate
我的意思是我们需要为每个类指定连接表的外键名称吗?

  1. 如果我想查找名称为“ABC”的指定组中的所有用户,如何使用 Grails 的 DynamicFinder?

非常感谢

【问题讨论】:

    标签: grails many-to-many dynamic-finders


    【解决方案1】:

    m2m 关系很少有拥有方,所以我总是觉得必须指定一个方才能让 GORM 正常工作很奇怪。正因为如此,我不这样做。我将连接表创建为域。然后事情就变得真的简单了。

    class UserGroup implements Serializable {
    
        User user
        Group group
    
        boolean equals(other) {
            if (!(other instanceof UserGroup)) {
                return false
            }
    
            other.user?.id == user?.id &&
                other.group?.id == group?.id
        }
    
        int hashCode() {
            def builder = new HashCodeBuilder()
            if (user) builder.append(user.id)
            if (group) builder.append(group.id)
            builder.toHashCode()
        }
    
        static UserGroup get(long userId, long groupId) {
            find 'from UserGroup where user.id=:userId and group.id=:groupId',
                [userId: userId, groupId: groupId]
        }
    
        static UserGroup create(User user, Group group, boolean flush = false) {
            new UserGroup(user: user, group: group).save(flush: flush, insert: true)
        }
    
        static boolean remove(User user, Group group, boolean flush = false) {
            UserGroup instance = UserGroup.findByUserAndGroup(user, group)
            instance ? instance.delete(flush: flush) : false
        }
    
        static void removeAll(User user) {
            executeUpdate 'DELETE FROM UserGroup WHERE user=:user', [user: user]
        }
    
        static void removeAll(Group group) {
            executeUpdate 'DELETE FROM UserGroup WHERE group=:group', [group: group]
        }
    
        static mapping = {
            id composite: ['group', 'user']
            version false
        }
    }
    

    然后你只需要在你的 User 和 Group 类中创建 getter。任何一个类中都没有 User 用户或 Group 组。无需使用 hasMany/belongsTo 映射它们,因为只需创建连接表即可,您可以通过创建 UserGroup 域来完成。

    class User {
       Set<Group> getGroups() {
        UserGroup.findAllByUser(this).collect { it.group } as Set
      }
    }
    
    class Group {
      Set<User> getUsers() {
        UserGroup.findAllByGroup(this).collect { it.user } as Set
      }
    }
    

    一旦你有了这些,你就可以使用你在用户组域中创建的方法和/或你可以在它上面使用查找器...

    def userGroupInstance = UserGroup.findByUserAndGroup(userInstance, groupInstance)
    def userGroups = UserGroup.findAllByUser(userInstance)
    def userGroupInstance = UserGroup.get(userId, groupId)
    

    你明白了。这个presentation by Burt Beckwith 更清楚地说明了为什么这是一个好方法以及其他一些提高性能的重要技巧。

    【讨论】:

      【解决方案2】:
      1. belongsTo 将创建另一个 M:1 关系(字段) - 你告诉在你的情况下是否有一个 User 的“主要组”。如果我只想强制执行至少一个组,我会为User.groups 使用自定义验证器,检查它不为空。

      2. (我不确定)- 我相信是的,如果密钥名称不同于默认的 Hibernat/GORM "userId"/"groupId"。

      3. findBy*() 方法在这里不起作用,您需要一个 CriteriaBuilder,例如 here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-30
        • 1970-01-01
        • 1970-01-01
        • 2016-08-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-21
        相关资源
        最近更新 更多