【问题标题】:Why grails throwing null pointer exception while accessing hasMany relationship first time?为什么grails在第一次访问hasMany关系时抛出空指针异常?
【发布时间】:2011-10-19 21:06:58
【问题描述】:

我有一个奇怪的问题。
我有两个域类 UserPost 字段:

class User {
  String name
  static hasMany = [posts: Post]
  static constraints = { }
}

class Post {
  String content
  long date = System.getTimeInMillis()
  static constraints = { }

  static belongsTo = [user: User]
  static mapping = {
    version: 'false'
  }
}

控制器代码为:

class UserController {
  def addUser = {
    def user
    if (User.count() == 0) {
      user = new User()
      user.name = "Manish Zedwal"
      user.save(flush: true)
    } else {
      user = User.get(1)
    }
    println "Posts count: " + user.posts.size()
    render "post count: " + user.posts.size()
 }
}

第一次访问 url http://localhost:8080/test/user/addUser 时,会抛出空指针异常,但之后就可以正常工作了。
这是我得到的例外

2011-08-04 15:41:25,847 [http-8080-1] ERROR errors.GrailsExceptionResolver  - Exception occurred when processing request: [GET] /test/user/addUser
Stacktrace follows:
java.lang.NullPointerException: Cannot invoke method size() on null object
        at test.UserController$_closure2.doCall(UserController.groovy:18)
        at test.UserController$_closure2.doCall(UserController.groovy)
        at java.lang.Thread.run(Thread.java:636)

第二次,它像魅力一样打印和渲染

Posts count: 0

在用户域类中,因为postspostshasMany 关系是Post 对象的列表,那么在获取空列表的大小时不应该出现空指针异常,而是应该为零。

任何帮助表示赞赏

【问题讨论】:

    标签: grails grails-orm


    【解决方案1】:

    当你像这样映射一个集合时,hasMany 声明会向你的类添加一个类型为 Set 且具有指定名称(在本例中为 posts)的字段。但是它不会初始化集合,所以它最初是空的。当您调用 addToPosts 时,它会检查它是否为 null,并在必要时创建一个新的空 Set,并将 Post 添加到集合中。但是如果你不调用addToPosts或者显式初始化set,它就会为null。

    当您从数据库加载User 时,Hibernate 将填充所有字段,并且集合包含在其中。它创建一个新的空集(一个修改感知PersistentSet),如果有任何实例,它就会向它添加实例。调用save() 不会从数据库中重新加载实例,所以空集仍然是空的。

    要让类在新类和持久类时表现相同,您可以向类中添加一个字段,就像 Rob 在他的回答中显示的那样,初始化为一个空集 (Set posts = [])

    【讨论】:

      【解决方案2】:

      您可以通过在映射旁边显式声明您的集合属性(带有值)来防止这种情况:

      class User {
          String name
          Set posts = []
          static hasMany = [posts: Post]
      }
      

      您可以定义您需要的集合类型。默认为Set,但如果需要维护秩序,可以考虑ListSortedSet

      【讨论】:

      • 是的,默认设置是 Set,但我使用 List,因为我将“posts”解释为具有排序的东西。不管怎样,SortedSet 可能更合适。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-19
      • 1970-01-01
      • 1970-01-01
      • 2013-04-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多