为什么grails在第一次访问hasMany关系时抛出空指针异常?

mj.*_*lla 20 grails grails-orm

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

class User {
  String name
  static hasMany = [posts: Post]
  static constraints = { }
}
Run Code Online (Sandbox Code Playgroud)

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

  static belongsTo = [user: User]
  static mapping = {
    version: 'false'
  }
}
Run Code Online (Sandbox Code Playgroud)

和控制器代码是:

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

第一次访问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)
Run Code Online (Sandbox Code Playgroud)

而且第二次,它打印并呈现精美的魅力

Posts count: 0
Run Code Online (Sandbox Code Playgroud)

在用户领域类的堂妹hasMany的关系posts,posts是列表Post对象则不应在获得空列表的大小空指针异常,而应该是零.

任何帮助赞赏

Bur*_*ith 30

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

当您User从数据库加载a时,Hibernate将填充所有字段,并且该集合包含在其中.它创建一个新的Set(一个可识别的修改PersistentSet),如果有的话,它会添加实例.但是,调用save()不会从数据库重新加载实例,因此空集仍将为null.

为了使类在新的时候以及在持久的时候表现相同,你可以在你的类中添加一个字段,就像Rob在他的答案中所示,初始化为空集(Set posts = [])


Rob*_*ska 11

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

class User {
    String name
    Set posts = []
    static hasMany = [posts: Post]
}
Run Code Online (Sandbox Code Playgroud)

您可以定义所需的集合类型.默认是Set,但如果您需要维护订单,您可以考虑ListSortedSet.

  • 应该是`Set posts = []` (2认同)