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

发布于 2024-11-27 21:27:13 字数 1564 浏览 1 评论 0原文

我有一个奇怪的问题。
我有两个域类 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

,它像魅力一样在用户域类中打印和渲染得很好,因为 hasMany 关系为 postsposts< /code> 是 Post 对象的列表,那么在获取空列表的大小时不应该出现空指针异常,而应该为零。

任何帮助表示赞赏

I have a strange problem.
I have two domain classes User and Post with fields:

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

and

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

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

and controller code is:

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

For the first time while accessing url http://localhost:8080/test/user/addUser, it throws null pointer exception, but after this works fine.
This is the exception I am getting

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)

and for second time, it prints and renders fine like charm

Posts count: 0

In user domain class, coz of hasMany relationship for posts, posts is a list of Post objects then there shouldn't be null pointer exception on getting the size of empty list, rather it should be zero.

Any help appreciated

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

千紇 2024-12-04 21:27:13

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

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

为了让类在新类和持久类时都以相同的方式运行,您可以向类中添加一个字段,就像 Rob 在他的答案中所示,初始化为一个空集 (Set posts = []

When you map a collection like that, the hasMany declaration adds a field of type Set with the specified name (in this case posts) to your class. It doesn't initialize the set though, so it's initially null. When you call addToPosts it checks if it's null and creates a new empty Set if necessary, and adds the Post to the collection. But if you don't call addToPosts or explicitly initialize the set, it will be null.

When you load a User from the database, Hibernate will populate all the fields, and the collection is included in that. It creates a new Set (a modification-aware PersistentSet) that's empty, and adds instances to it if there are any. Calling save() doesn't reload the instance from the database though, so the null set will still be null.

To get the class to behave the same way when it's new and when it's persistent, you can add a field to your class Like Rob showed in his answer, initialized to an empty set (Set posts = [])

阳光下慵懒的猫 2024-12-04 21:27:13

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

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

您可以定义所需的集合类型。默认为 Set,但如果您需要保持顺序,您可以考虑 ListSortedSet

You can prevent this by explicitly declaring your collection property (with a value) alongside your mapping:

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

You can define the collection type you need. The default is Set, but if you need to maintain order, you might consider List or SortedSet.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文