Grails Gorm:Object引用未保存的瞬态实例

Dan*_*iel 5 grails grails-orm

在Grails中保存Trip的实例时,我得到以下异常:

2011-01-26 22:37:42,801 [http-8090-5] ERROR errors.GrailsExceptionResolver - 对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例:Rower org.hibernate.TransientObjectException:object引用未保存的瞬态实例 - 在冲洗之前保存瞬态实例:Rower

这个概念很简单:对于一个游船,你需要一些划船者,一个舵手(也是一个划船者)和一艘船:

旅行看起来像(缩短):

class Trip {
    Boat boat;
    Rower coxwain;

    static belongsTo = [Rower,Boat]
    static hasMany = [rowers:Rower]
}
Run Code Online (Sandbox Code Playgroud)

和划船(缩短)

class Rower { 
    String firstname;
    String name;
    Rower reference;

    static hasMany = [trips:Trip];
    static mappedBy = [trips:"rowers"]
}
Run Code Online (Sandbox Code Playgroud)

然后行程保存在控制器中,如:

def save = {
        def trip = new Trip(params)

        // adding Rowers to Trip
        if (params.rower instanceof String) {
            def r = Rower.get(params?.rower)

            if (r != null) {
                trip.addToRowers(r)
            }
        } else {
            params?.rower?.each{
                rowerid ->
                def r = Rower.get(rowerid)
                log.info("rowerid (asList): " + rowerid)
                if (r != null) {
                    trip.addToRowers(r)
                }
            }
        } 

        // saving the new Trip -> EXCEPTION IN NEXT LINE
        if(!trip.hasErrors() && trip.save(flush:true)) {
          // ...
        }
        // ...
}
Run Code Online (Sandbox Code Playgroud)

我想我已经确定了域之间的关系是正确的.在将Rower添加到Trip中时,Rower不会更改.为什么Grails希望它保存?为什么它是一个瞬态实例?

Gua*_*ius 7

不幸的是,这是GORM处理事物的方式的问题,或者更具体地说是它期望您处理瞬态的方式.如果您不首先将包含的类持久保存到数据库(在本例中为Rowers),则每次都会得到此异常.

使用GORM,您必须以自下而上的方式保存和附加,或者当grails用于刷新下一个实例的连接时,您将获得瞬态实例异常.该实例是"瞬态的",因为它只是一个内存引用.要保留父级,GORM需要将父级链接到数据库中的子级.如果孩子没有被坚持,就无法做到这一点,这就是异常的来源.

希望有更好的消息.这不是很难,但它会因复杂的层次结构而变得烦人.


Med*_*rod 0

我认为您必须先保存行程,然后才能将流动站添加到行程中。此外,在验证和/或保存旅行之前检查旅行是否有错误是没有意义的。

尝试这个:

if(trip.validate() && trip.save(flush:true)) {
    if (r != null) {
       trip.addToRowers(r)
    }  
}
Run Code Online (Sandbox Code Playgroud)