动态查找与Grails多对多关系 [英] Dynamic finders with Grails many-to-many relationship

查看:111
本文介绍了动态查找与Grails多对多关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有2个由多对多关系映射的域类。我遵循Grails文档的说明,但在处理这些域上的数据时仍然遇到一些问题。这里是我的2个领域的类:

pre $ class User {
字符串名称
int age
字符串作业
static hasMany = [groups:Group]
static belongsTo = [org:Organization]
}

class Group {
String groupName
字符串代码
static hasMany = [会员:用户]
}

我的问题是:

1.上述关系要求一个类持有belongsTo作为关系的所有者。在这种情况下,用户属于Group,但我不知道如何将belongsTo设置为User类,因为Grails建议的标准语法是static belongsTo = [Group](只需指定所有者类名),所以我不能:

- 把它放到存在belongsTo中就像这样:static belongsTo = [org:Organization,Group]

- 或者定义另一个belongsTo像这样:static belongsTo = [Group]


  1. 下面的例子是对的:

    class Book {
    String title
    static belongsTo = Author
    static hasMany = [authors:Author]

     作者joinTable:[name:mm_author_books,key:'mm_book_id'] 
    }

    }
    class作者{
    字符串名称
    static hasMany = [books:Book]

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

    }


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


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

非常感谢你

解决方案

m2m关系非常罕见,所以我一直觉得奇怪的是必须指定一个让GORM正常工作。正因为如此,我不这样做。我将连接表创建为一个域。然后事情变得简单。

  class UserGroup实现Serializable {

用户用户
组用户

布尔等于(其他){
if(!(other(UserGroup)instanceof)){
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其中user.id =:userId和group.id =:groupId',
[userId:userId,groupId:groupId]


static UserGroup create(User user,Group group,boolean flush = false){
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.delete(flush:flush):false
}

static void removeAll(User user){
executeUpdate'DELETE FROM UserGroup WHERE user =:user',[user:用户]
}

static void removeAll(Group group){
executeUpdate'DELETE FROM UserGroup WHERE group =:group',[group:group]
}

static mapping = {
id复合:['group','user']
版本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<使用者名称> getUsers(){
UserGroup.findAllByGroup(this).collect {it.user} as Set
}
}

完成这些操作之后,您可以使用您在UserGroup域中创建的方法,或者您可以在其上使用查找器...


$ (userInstance,groupInstance)
def userGroups = UserGroup.findAllByUser(userInstance)
def userGroupInstance = UserGroup.get(userGroup.getByUserAndGroup) userId,groupId)

你明白了。这份 Burt Beckwith的演讲更清晰地说明了为什么这是一个很好的方法以及其他一些方法性能提升的重要提示。


I have 2 domain classes which are mapped by many-to-many relationship. I followed the instruction of Grails documentation, but I still have some problem when processing data on those domains. Here are my 2 domain classes:

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

My problems are:
1. The above relationship require one class hold belongsTo to be the "owner" of the relationship. In this context, the User belongs to the Group, but I do not know how to put the belongsTo to User class, because the standard syntax that Grails suggest is static belongsTo = [Group] (just specify the owner class name), so I cannot:
- put it into the exist belongsTo like this: static belongsTo = [org : Organization, Group]
- or define another belongsTo like this: static belongsTo = [Group]

  1. Is below example right:

    class Book { String title static belongsTo = Author static hasMany = [authors:Author]

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

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

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

    }

(Ref link: Many-to-Many link tables in grails (GORM) / hibernate)
I mean that do we need to specify the name of foreign key of the join table for each class?

  1. If I want to find all User that are members of a specified Group whose name is "ABC", how can I use the DynamicFinder of Grails?

Thank you so much

解决方案

It is very rare that m2m relationships have an owning side, so I've always found it odd to have to specify one for GORM to work correctly. Because of this, I don't do it this way. I create the join table as a domain. Then things get really simple.

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
    }
}

Then you just need to create the getters in your User and Group class. You won't have User user or Group group in either class. There is no need to map them with hasMany/belongsTo because all that will do is create the join table, which you've done by creating the UserGroup domain.

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
  }
}

Once you have these in place you can use the methods you created in the UserGroup domain and/or you can use finders on it...

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

You get the idea. This presentation by Burt Beckwith sheds more light on why this is a good approach along with some other great tips for performance increases.

这篇关于动态查找与Grails多对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆