简体   繁体   中英

Grails GORM: How to 'null' a property of a child in a one-to-many relationship?

I have a undirectional one to many relationship of two domain classes:

package net.peddn

class User {
    static hasMany = [texts: Text]
    String username 
}

and

package net.peddn

class Text {

    long creator
    String title

    static constraints = {
        creator( nullable: true )
    }   
}

my User controller looks like this:

package net.peddn

class UserController {

static scaffold = true

    def delete() {

        def userInstance = User.get(params.id)

        userInstance.texts.each { text ->
            text.creator = null
        }           

        userInstance.delete(flush: true)

}

my BootStrap.groovy looks like this:

import net.peddn.Text
import net.peddn.User

class BootStrap {

    def init = { servletContext ->

    User user = new User(username: "username")

    user.save(flush: true)

    Text text1 = new Text(title: "titel 1", creator: user.id)

    Text text2 = new Text(title: "titel 2", creator: user.id)

    user.addToTexts(text1)

    user.addToTexts(text2)

    user.save(flush: true)

    }

    def destroy = {
    }

}

When I now try to delete my User I get the following error:

| Server running. Browse to http://localhost:8080/usertexts
| Error 2012-06-17 19:33:49,581 [http-bio-8080-exec-4] ERROR errors.GrailsExceptionResolver  - IllegalArgumentException occurred when processing request: [POST] /usertexts/user/index - parameters:
id: 1
_action_delete: Löschen
Stacktrace follows:
Message: null
    Line | Method
->>   21 | doCall    in net.peddn.UserController$_delete_closure1
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|     19 | delete    in net.peddn.UserController
|   1110 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    603 | run       in java.util.concurrent.ThreadPoolExecutor$Worker
^    722 | run . . . in java.lang.Thread

If i change the code to

text.creator = 0

in UserController.groovy is works perfectly.

By the way: I used this domain model because I don't want the Text objects to be deleted when a User will be deleted. But I also want to know who created the Text object. If someone has a better solution for this problem PLEASE let me know.

Thanks! Peter

With your current implementation please try if this works:

    def delete() {

        def userInstance = User.get(params.id)

        userInstance.texts.each { text ->
            userInstance.removeFromTexts(text)
        }           

        userInstance.delete(flush: true)
    }

If you want bidirectional relation User-Texts and you don't want texts to be deleted when user is deleted you can change this behaviour. Check documentation section on cascades in Hibernate here: custom cascades . You can change mapping like this:

class User {
    static hasMany = [texts: Text]

    static mapping = {
        texts cascade: "save-update"
    }
}

Finally I found the right hint . It seems that this is a casting problem. see:

Groovy Primitive Type Cast Gotcha When Upgrading to Grails 2.0

So i changed the primitive "long" property of the Text domain class to its "boxed" version "Long":

package net.peddn

class Text {

    Long creator
    String title

    static constraints = {
        creator( nullable: true )
    }   
}

and now the property can be set to null!

Thank you Tomasz for your help!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM