具有Grails多对多关系的动态查找器

Đin*_*hâu 2 grails many-to-many dynamic-finders

我有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]
}
Run Code Online (Sandbox Code Playgroud)

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

  1. 以下示例正确:

    class Book {String title static belongsTo =作者static hasMany = [作者:作者]

    static mapping = {
        authors joinTable:[name:"mm_author_books", key:'mm_book_id' ]
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

    static mapping = {
        books joinTable:[name:"mm_author_books", key:'mm_author_id']
    }
    
    Run Code Online (Sandbox Code Playgroud)

    }

(参考链接:Grails中的多对多链接表(GORM)/ hibernate)
我的意思是我们是否需要为每个类指定连接表的外键名称?

  1. 如果我想查找属于名称为"ABC"的指定组成员的所有用户,如何使用Grails的DynamicFinder?

非常感谢

Gre*_*egg 6

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
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您只需在User和Group类中创建getter.您不会在任何一个类中拥有用户用户或组.不需要使用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
  }
}
Run Code Online (Sandbox Code Playgroud)

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

def userGroupInstance = UserGroup.findByUserAndGroup(userInstance, groupInstance)
def userGroups = UserGroup.findAllByUser(userInstance)
def userGroupInstance = UserGroup.get(userId, groupId)
Run Code Online (Sandbox Code Playgroud)

你明白了.Burt Beckwith的这次演讲更加清楚了解为什么这是一个很好的方法以及其他一些提高性能的好方法.