2011-01-26 68 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

相關問題