我有一个奇怪的问题
我有两个域类User
和Post
,其中包含字段:
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
的{{1}}关系的coz,posts
是posts
个对象的列表,那么获取时不应该有空指针异常空列表的大小,而不应该为零。
任何帮助表示赞赏
答案 0 :(得分:30)
当您映射这样的集合时,hasMany
声明会向您的类添加一个类型为Set
且具有指定名称(在本例中为posts
)的字段。它不会初始化集合,因此它最初为null。当你调用addToPosts
时,它会检查它是否为null并在必要时创建一个新的空集,并将Post添加到集合中。但是,如果您不调用addToPosts
或显式初始化该集,则它将为null。
当您从数据库加载User
时,Hibernate将填充所有字段,并且该集合包含在其中。它创建一个新的Set(一个修改意识的PersistentSet
),它是空的,如果有的话,它会添加实例。调用save()
不会从数据库重新加载实例,因此空集仍将为null。
为了让类在新的时候以及在持久化时的行为相同,你可以在你的类中添加一个字段,如Rob在他的答案中所示,初始化为空集(Set posts = []
)
答案 1 :(得分:11)
您可以通过在映射旁边显式声明您的集合属性(带值)来阻止这种情况:
class User {
String name
Set posts = []
static hasMany = [posts: Post]
}
您可以定义所需的集合类型。默认值为Set
,但如果您需要维护订单,则可以考虑List
或SortedSet
。