2011-01-26 119 views
5

我的Grails节省旅行的实例时出现以下情况例外:Grails的格姆:对象引用一个未保存的瞬态的实例

2011-01-26 22:37:42,801 [HTTP-8090-5] ERROR errors.GrailsExceptionResolver - 对象引用一个未保存的瞬态的实例 - 在冲洗前保存 瞬态的实例:赛艇 org.hibernate.TransientObjectException: 对象引用一个未保存的瞬态 实例 - 冲洗之前保存的瞬态的实例 :赛艇

这个概念很简单:因为你需要一些划船一个boattrip,一个coxwain(也划手)和船:

旅行的样子(缩短):

class Trip { 
    Boat boat; 
    Rower coxwain; 

    static belongsTo = [Rower,Boat] 
    static hasMany = [rowers:Rower] 
} 

和赛艇(缩短)

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

    static hasMany = [trips:Trip]; 
    static mappedBy = [trips:"rowers"] 
} 

跳闸然后被保存在控制器等:

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)) { 
      // ... 
     } 
     // ... 
} 

我想我已经设置了正确的域之间的关系。 划船者被添加到旅行中时不会更改。为什么Grails想要它保存?为什么它是一个短暂的实例?

+0

是否在这两个控制器模块发生(即如果和其他)? – 2011-01-26 22:19:14

回答

0

我认为你必须保存行程,然后才能将漫游车添加到行程中。 在验证和/或保存之前,检查旅程是否有错误也是没有意义的。

试试这个:

if(trip.validate() && trip.save(flush:true)) { 
    if (r != null) { 
     trip.addToRowers(r) 
    } 
} 
0

起初我还以为是级联做保存和属于关联,如The Grails Reference节5.2.1.3和Gorm Gotchas part 2描述。然而,由于Rowers已经在数据库中,我认为它应该有效。域模型对我来说很复杂,您需要做的就是简化它并使用Grails控制台运行一些测试(在项目目录中运行grails控制台)。首先在Trip和Rower之间创建一个基本的多对多,并让它执行所需的代码。然后逐位添加其他部分,如Rower对其自身的引用。我不确定mappedBy部分是否有必要。

1

问题有点不同。 它在这里:

def trip = new Trip(params) 

它引用,这是不设置(ID =返回-1)(类赛艇运动员)一coxwain。这构造了一个新的Rower而不是'null'值。这是'未保存的瞬态实例'。 如果我首先检查一个有效的实例,那么它可以工作:-)

感谢您的帮助!

6

不幸的是,这是GORM处理事物的方式的一个问题,或者更具体地说是它期望您处理瞬变的方式。如果您没有将包含的类首先保存到数据库(本例中是Rowers),那么您每次都会得到此异常。

对于GORM,您必须以自下而上的方式进行保存和附加,或者当grails将刷新下一个实例的连接时,您将获得暂时实例异常。该实例是'暂时的',因为它只是一个内存中的参考。要坚持父母,GORM需要将父母链接到数据库中的孩子。如果孩子没有坚持下去,就没有办法做到这一点,这是例外来自的地方。

希望那里有更好的消息。并不那么困难,但它会因复杂的层次结构而变得烦人。

1

只是一个快速的笔记对任何人处理与同名的单个或多个参数,使用params.list("parameterName")帮助你总是可以返回一个列表

... 

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

    ... 

可能变得有点更巧妙的

... 

    // adding Rowers to Trip 
    for(rower in params.list("rower") { 
     def r = Rower.get(rower) 
     if(r) trip.addToRowers(r) 
    } 

    ... 

你可以找到它躲在6.1.12 Simple Type Converters

相关问题