Java Grails:GORM:遍历多对多关系

Java Grails:GORM:遍历多对多关系,java,hibernate,grails,many-to-many,gorm,Java,Hibernate,Grails,Many To Many,Gorm,我有两个域对象,User和SystemRights(这是一个多对多的对象,因此一个用户可以拥有多个权限,一个权限可以由多个用户拥有)。我正在寻找一种简单的方法来检查用户是否拥有所需的权限 用户域 class User { static hasMany = [systemRights: SystemRight, enterpriseUsers: EnterpriseUser] String email; String passwordHash; } class

我有两个域对象,User和SystemRights(这是一个多对多的对象,因此一个用户可以拥有多个权限,一个权限可以由多个用户拥有)。我正在寻找一种简单的方法来检查用户是否拥有所需的权限

用户域

class User {

    static hasMany = [systemRights: SystemRight, enterpriseUsers: EnterpriseUser]

    String email;   
    String passwordHash;
}
class SystemRight {

    public static final String LOGIN = "LOGIN"
    public static final String MODIFY_ALL_ENTERPRISES = "MODIFY_ALL_ENTERPRISES"
    public static final String ADMINISTER_SYSTEM = "ADMINISTER_SYSTEM"
    public static final String VALIDATE_SUPPLIER_SCORECARDS = "VALIDATE_SUPPLIER_SCORECARDS"

    static hasMany = [users:User]
    static belongsTo = User

    String name
}
public boolean hasRights(List<String> requiredRights) {

    for (String requiredRight : requiredRights) {

        def has = false

        for (SystemRight userRight : user.systemRights) {
            if (userRight.name == requiredRight) {
                has = true
                break;
            }
        }

        if (has == false) {
            return false;
        }            
    }

    return true        

}
SystemRight域

class User {

    static hasMany = [systemRights: SystemRight, enterpriseUsers: EnterpriseUser]

    String email;   
    String passwordHash;
}
class SystemRight {

    public static final String LOGIN = "LOGIN"
    public static final String MODIFY_ALL_ENTERPRISES = "MODIFY_ALL_ENTERPRISES"
    public static final String ADMINISTER_SYSTEM = "ADMINISTER_SYSTEM"
    public static final String VALIDATE_SUPPLIER_SCORECARDS = "VALIDATE_SUPPLIER_SCORECARDS"

    static hasMany = [users:User]
    static belongsTo = User

    String name
}
public boolean hasRights(List<String> requiredRights) {

    for (String requiredRight : requiredRights) {

        def has = false

        for (SystemRight userRight : user.systemRights) {
            if (userRight.name == requiredRight) {
                has = true
                break;
            }
        }

        if (has == false) {
            return false;
        }            
    }

    return true        

}
以下内容对我不起作用:

在User.class中

public boolean hasRights(List<String> requiredRights) {

    def userHasRight = SystemRight.findByUserAndSystemRight (this, SystemRight.findByName(requiredRight));

    // Nor this

    def userHasRight = this.systemRights.contains(SystemRight.findByName(requiredRight));

}
public boolean权限(列出所需权限){
def userHasRight=SystemRight.findByUserAndSystemRight(这是SystemRight.findByName(requiredRight));
//也不是这个
def userHasRight=this.systemRights.contains(SystemRight.findByName(requiredRight));
}
当前可怕的解决方案

class User {

    static hasMany = [systemRights: SystemRight, enterpriseUsers: EnterpriseUser]

    String email;   
    String passwordHash;
}
class SystemRight {

    public static final String LOGIN = "LOGIN"
    public static final String MODIFY_ALL_ENTERPRISES = "MODIFY_ALL_ENTERPRISES"
    public static final String ADMINISTER_SYSTEM = "ADMINISTER_SYSTEM"
    public static final String VALIDATE_SUPPLIER_SCORECARDS = "VALIDATE_SUPPLIER_SCORECARDS"

    static hasMany = [users:User]
    static belongsTo = User

    String name
}
public boolean hasRights(List<String> requiredRights) {

    for (String requiredRight : requiredRights) {

        def has = false

        for (SystemRight userRight : user.systemRights) {
            if (userRight.name == requiredRight) {
                has = true
                break;
            }
        }

        if (has == false) {
            return false;
        }            
    }

    return true        

}
public boolean权限(列出所需权限){
for(字符串requiredRight:requiredRights){
def has=false
for(SystemRight userRight:user.systemRights){
if(userRight.name==requiredRight){
has=true
打破
}
}
如果(has==false){
返回false;
}            
}
返回真值
}

如果你能够/愿意改变一些事情,我强烈建议你做以下几点。这会让你的生活轻松很多

首先,从这两个域中删除hasMany for SystemRight和User,并从SystemRight中删除belongsTo User

接下来,创建表示联接表的域

class UserSystemRight {
   User user
   SystemRight systemRight

   boolean equals(other) {
      if (!(other instanceof UserSystemRight)) {
          return false
      }
      other.user?.id == user?.id && other.systemRight?.id == systemRight?.id
   }

   int hashCode() {
      def builder = new HashCodeBuilder()
      if (user) builder.append(user.id)
      if (systemRight) builder.append(systemRight.id)
      builder.toHashCode()
   }


   // add some more convenience methods here if you want like...
   static UserSystemRight get(long userId, long systemRightId, String systemRightName) {
       find 'from UserSystemRight where user.id=:userId and systemRight.id=:systemRightId and systemRight.name=:systemRightName',
            [userId: userId, systemRightId: systemRightId, systemRightName: systemRightName]
   }
}
然后,在用户类中可以添加以下方法:

Set<SystemRight> getSystemRights() {
    UserSystemRight.findAllByUser(this).collect { it.systemRight } as Set
}
Set getSystemRights(){
UserSystemRight.findallbyser(this).collect{it.systemRight}作为集合
}
然后,将其添加到SystemRight域:

Set<User> getUsers() {
    UserSystemRight.findAllBySystemRight(this).collect { it.user } as Set
}
Set getUsers(){
UserSystemRight.findAllBySystemRight(this).collect{it.user}作为集合
}

要更详细地解释为什么这种方法除了实际解决您的问题外,还充满了胜利。

如果您能够/愿意改变一些事情,我强烈建议您执行以下操作。这会让你的生活轻松很多

首先,从这两个域中删除hasMany for SystemRight和User,并从SystemRight中删除belongsTo User

接下来,创建表示联接表的域

class UserSystemRight {
   User user
   SystemRight systemRight

   boolean equals(other) {
      if (!(other instanceof UserSystemRight)) {
          return false
      }
      other.user?.id == user?.id && other.systemRight?.id == systemRight?.id
   }

   int hashCode() {
      def builder = new HashCodeBuilder()
      if (user) builder.append(user.id)
      if (systemRight) builder.append(systemRight.id)
      builder.toHashCode()
   }


   // add some more convenience methods here if you want like...
   static UserSystemRight get(long userId, long systemRightId, String systemRightName) {
       find 'from UserSystemRight where user.id=:userId and systemRight.id=:systemRightId and systemRight.name=:systemRightName',
            [userId: userId, systemRightId: systemRightId, systemRightName: systemRightName]
   }
}
然后,在用户类中可以添加以下方法:

Set<SystemRight> getSystemRights() {
    UserSystemRight.findAllByUser(this).collect { it.systemRight } as Set
}
Set getSystemRights(){
UserSystemRight.findallbyser(this).collect{it.systemRight}作为集合
}
然后,将其添加到SystemRight域:

Set<User> getUsers() {
    UserSystemRight.findAllBySystemRight(this).collect { it.user } as Set
}
Set getUsers(){
UserSystemRight.findAllBySystemRight(this).collect{it.user}作为集合
}

要更详细地解释为什么这种方法除了实际解决您的问题外,还充满了胜利,请看下面的内容

public boolean hasRights(List<String> requiredRights) {
    return null != (this.systemRights.find { requiredRights.contains(it) });
}
public boolean权限(列出所需权限){
返回null!=(this.systemRights.find{requiredRights.contains(it)});
}

(未经测试:这里是Groovy新手)

以下内容如何

public boolean hasRights(List<String> requiredRights) {
    return null != (this.systemRights.find { requiredRights.contains(it) });
}
public boolean权限(列出所需权限){
返回null!=(this.systemRights.find{requiredRights.contains(it)});
}

(未测试:这里是Groovy newbie)

我一定会尝试在数据库中解决这个问题

def relevantUserRights = SystemRight.withCriteria {
    eq("user", this)
    "in"("name", requiredRights);
}

return relevantUserRights.size() == requiredRights.size()

我一定会在数据库中解决这个问题

def relevantUserRights = SystemRight.withCriteria {
    eq("user", this)
    "in"("name", requiredRights);
}

return relevantUserRights.size() == requiredRights.size()

嗨,格雷格,谢谢你的回答。你是在建议失去多对多的关系吗。由于这些限制,我对User和Enterprise以及UserEnterprise这样做了。如果这是你的建议,那么我想我会终止我项目中所有的m2m关系。它仍然是m2m,你只是自己管理联接表。嗨,Gregg,谢谢你的回答。你是在建议失去多对多的关系吗。由于这些限制,我对User和Enterprise以及UserEnterprise这样做了。如果这是你的建议,那么我想我将终止我项目中的所有m2m关系。它仍然是m2m,你只是自己管理联接表。我完全喜欢null!=戏法以前从没想过!我完全喜欢空的戏法以前从没想过+谢谢你。我对此进行了测试,效果良好,但我决定使用@Gregg的答案并重构我的域对象来创建一个显式连接表。+1谢谢。我对此进行了测试,结果很有效,但我决定使用@Gregg的答案并重构我的域对象来创建一个显式连接表。