query - grails tutorial
¿Por qué Grails lanza una excepción de puntero nulo al acceder a la relación hasMany por primera vez? (2)
Cuando hasMany
una colección como esa, la declaración hasMany
agrega un campo de tipo Set
con el nombre especificado (en este caso, posts
) a su clase. Sin embargo, no inicializa el conjunto, por lo que inicialmente es nulo. Cuando llama a addToPosts
, comprueba si es nulo y crea un nuevo Conjunto vacío si es necesario, y agrega la Publicación a la colección. Pero si no llama a addToPosts
o inicializa explícitamente el conjunto, será nulo.
Cuando carga un User
de la base de datos, Hibernate llenará todos los campos y la colección se incluirá en eso. Crea un nuevo conjunto (un conjunto PersistentSet
que tiene en cuenta la modificación) que está vacío, y le agrega instancias si las hay. Sin embargo, llamar a save()
no vuelve a cargar la instancia desde la base de datos, por lo que el conjunto nulo seguirá siendo nulo.
Para que la clase se comporte de la misma manera cuando es nueva y cuando es persistente, puede agregar un campo a su clase. Como mostró Rob en su respuesta, se inicializó en un conjunto vacío ( Set posts = []
)
Tengo un problema extraño.
Tengo dos clases de dominio User
y Post
con campos:
class User {
String name
static hasMany = [posts: Post]
static constraints = { }
}
y
class Post {
String content
long date = System.getTimeInMillis()
static constraints = { }
static belongsTo = [user: User]
static mapping = {
version: ''false''
}
}
y el código del controlador es:
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()
}
}
Por primera vez, al acceder a la URL http://localhost:8080/test/user/addUser
, arroja una excepción de puntero nulo, pero después de esto funciona bien.
Esta es la excepción que estoy recibiendo
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)
Y por segunda vez, se imprime y queda bien como encanto.
Posts count: 0
En la clase de dominio de usuario, por la relación de hasMany
para posts
, las posts
son una lista de objetos de hasMany
, entonces no debería haber una excepción de puntero nulo al obtener el tamaño de la lista vacía, sino que debería ser cero.
Cualquier ayuda apreciada
Puede evitar esto declarando explícitamente su propiedad de colección (con un valor) junto con su asignación:
class User {
String name
Set posts = []
static hasMany = [posts: Post]
}
Puede definir el tipo de colección que necesita. El valor predeterminado es Set
, pero si necesita mantener el orden, puede considerar la SortedSet
List
o SortedSet
.