Grails 2.4.4从hasmany String关系中删除所有项目

时间:2015-11-23 07:55:47

标签: grails

我有一个User类,有许多组织,组织是String UID。

class User implements Serializable {
  ...
  List organizations
  static hasMany = [organizations: String]
  ...
}

要更新用户实例,我需要在添加更新的uid之前从“组织”中删除所有字符串,但它不起作用。删除后,将相同的组织重新保存到集合中并保存用户实例。

我尝试了很多方法:

// 1
user.organizations.clear()

// 2
def orgsToDelete = [] // this is to avoid concurrent modification exception
orgsToDelete += user.organizations
orgsToDelete.each { orguid ->
   user.removeFromOrganizations(orguid)
}

在1或2之后,user.organizations为空,但是当我这样做时:

user.save(flush:true)

我得到了与clear / removeFromOrganizations之前相同的组织

我无法执行user.organizations.each {it.delete()},因为这些项不是域类,而是字符串。

另一个奇怪的事情是我有一个自定义验证器来检查集合是否有任何项目,并且它似乎没有任何错误,组织为空的事件,这是我的验证器:

organizations validator: { val, obj ->
  if (obj.organizations.size() == 0) return false
  return true
}

当我在控制器更新操作上执行此操作时,它会显示hasErrors()== false

if (userInstance.hasErrors())
{
   println "has errors"
   respond userInstance.errors, view:'edit'
   return
}

有什么想法吗?

这是控制器:https://github.com/ppazos/cabolabs-ehrserver/blob/master/grails-app/controllers/com/cabolabs/security/UserController.groovy#L199-L237

2 个答案:

答案 0 :(得分:0)

使用您自己的域类而不是String作为集合的元素,例如:

class Organization {
  String name
  static belongsTo = [ User ]
}

然后你应该能够通过

正确删除孩子
user.organisations.clear()
user.save()

您面临的行为的原因是,String实例被映射到没有user的后向引用的表。这导致了这样的情况:string表中的记录实际上没有被删除,并且在下一次数据库调用时被加载。

答案 1 :(得分:0)

我已经阅读了您的项目代码,并且您已经设置了DataSource。您正在使用H2内存BBDD,而是使用MySQL驱动程序(在开发环境中)。它看起来不太好看。正确设置,然后重试。

我测试了你的模型,并使用了:

user.organizations.clear()

没有任何问题,甚至使用您的自定义验证器。

另一方面,您应该使用服务代替所有业务逻辑,而不是控制器。因为默认情况下服务是事务性的。

以下是我所做的更改,并且有效:

//   List organizations = []
   static hasMany = [organizations: String] 

   static mapping = {
      password column: '`password`'
      // organizations lazy: false
   }

删除列表组织。在DataSource开发环境中使用带有此配置的H2数据源:

       dbCreate = "create-drop" 
       url = "jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
       username = "sa"
       password = ""

这段代码就像一个魅力:

   def clearOrganizationFromUser(){

      //creating user with timestamp
      User user = new User(username: 'username' + new Date(), password: 'password', email: 'email@email.es', accountExpired: false, accountLocked: false,
         passwordExpired: false)
      List<String> organizations = []
      10.times{
         organizations << "organization $it"
      }

      organizations.each{ String organization ->
         user.addToOrganizations(organization)
      }

      user.save()
      println "Organizations after saving: ${user.organizations}"

      //Its not neccesary but I did it for showing that organization are persisted in DDBB
      User newUserFromDDBB = User.get(user.id)

      //deleting organization
      newUserFromDDBB.organizations.clear()
      newUserFromDDBB.save()

      println "---> Organizations after deleting: ${newUserFromDDBB.organizations}"

   }

希望它有效。如果有,请标记为已解决。