2012-10-22 45 views
5

我目前正在開發一個Grails應用程序,我正在使用Spring Security和UI插件。我創建了用戶級和其他地區類,我有哪些可以看到下面的關係:Grails - 在刷新grails之前保存瞬態實例錯誤?

用戶類別:

class User { 

    transient springSecurityService 

    String username 
    String email 
    String password 
    boolean enabled 
    boolean accountExpired 
    boolean accountLocked 
    boolean passwordExpired 

    static belongsTo = [area:Areas] 

     ....... 
} 

Area類:

class Areas { 

    String name 

    static hasMany = [users:User] 

} 

正如你所看到的從一個用戶可以鏈接到一個區域,但一個區域可能有很多用戶。這一切都正常工作,當我啓動應用程序時,所有數據都被正確添加。然而,我得到以下錯誤,當我嘗試用一​​種形式來創建一個新用戶:

object references an unsaved transient instance - save the transient instance before flushing: com.website.Area 
下面

是我使用保存信息的控制器代碼:

def save = {  
     def user = lookupUserClass().newInstance(params) 

     if (params.password) { 
      String salt = saltSource instanceof NullSaltSource ? null : params.username 
      user.password = springSecurityUiService.encodePassword(params.password, salt) 
     } 

     if (!user.save(flush: true)) { 
      render view: 'create', model: [user: user, authorityList: sortedRoles()] 
      return 
     } 

     addRoles(user) 
     flash.message = "${message(code: 'default.created.message', args: [message(code: 'user.label', default: 'User'), user.id])}" 
     redirect action: edit, id: user.id 
    } 

,這裏是一個

<table> 
     <tbody> 

      <s2ui:textFieldRow name='username' labelCode='user.username.label' bean="${user}" 
          labelCodeDefault='Username' value="${user?.username}"/> 

      <s2ui:passwordFieldRow name='password' labelCode='user.password.label' bean="${user}" 
           labelCodeDefault='Password' value="${user?.password}"/> 

      <s2ui:textFieldRow name='email' labelCode='user.email.label' bean="${user}" 
           labelCodeDefault='E-Mail' value="${user?.email}"/> 

      <s2ui:textFieldRow readonly='yes' name='area.name' labelCode='user.area.label' bean="${user}" 
           labelCodeDefault='Department' value="${area.name}"/> 


      <s2ui:checkboxRow name='enabled' labelCode='user.enabled.label' bean="${user}" 
          labelCodeDefault='Enabled' value="${user?.enabled}"/> 

      <s2ui:checkboxRow name='accountExpired' labelCode='user.accountExpired.label' bean="${user}" 
          labelCodeDefault='Account Expired' value="${user?.accountExpired}"/> 

      <s2ui:checkboxRow name='accountLocked' labelCode='user.accountLocked.label' bean="${user}" 
          labelCodeDefault='Account Locked' value="${user?.accountLocked}"/> 

      <s2ui:checkboxRow name='passwordExpired' labelCode='user.passwordExpired.label' bean="${user}" 
          labelCodeDefault='Password Expired' value="${user?.passwordExpired}"/> 
     </tbody> 
     </table> 

我已經看過這個,我相信這是我想保存GORM對象的方式,我應該試圖挽救之前可能保存父(區):什麼樣的GSP看起來樣用戶。然而,在創建用戶之前區域將始終存在,因此我不需要再次創建區域,我該如何處理?我嘗試了「withTransaction」功能,並且收效甚微。

如果可能,我真的很感激這方面的幫助。

感謝

編輯......

我已經在控制跟蹤的問題這一行:

RegistrationCode registrationCode = springSecurityUiService.register(user, command.password, salt) 

這對我說,這個功能調用保存函數用於用戶對象,但是需要首先保存Area的關係。有人知道SpringSecurityUi爲了幫助我嗎?

感謝

+0

將springsecurityservice放入控制器,而不是域級。 – marko

+0

您能否給我舉個例子?因爲springsecurityservice一直在那裏 – user723858

+0

錯誤不會與錯誤說的「com.website.Area」類相關嗎?謝謝 – user723858

回答

7

刪除屬於關聯看到

object references an unsaved transient instance - save the transient instance before flushing: com.website.Area 
錯誤信息

......當您嘗試保存不存在的父級(即Area)時發生來自孩子(即用戶)實體的實體。如您所指出的那樣,如果這是您保存新用戶的地方,則可能在RegistrationController.register方法中發生錯誤。

RegistrationCode registrationCode = springSecurityUiService.register(user, command.password, salt) 

您只需要更新RegistrationCode。在寄存器呼叫之前註冊帶邏輯的方法將Area分配給用戶(假設Area已經存在),下面是一個簡單的例子。

class RegistrationController .. 
.. 
def area = Area.findByName(command.areaName) 
def user = lookupUserClass().newInstance(email: command.email, username: command.username, 
       accountLocked: true, enabled: true, area: area) 
RegistrationCode registrationCode = springSecurityUiService.register(user, command.password, salt) 

有兩點要注意:

  • 您從GSP視圖傳回「area.name」,所以你需要更新/覆蓋RegisterCommand到包括
  • 是您使用區域「名稱」作爲標識符安全嗎?在你的類定義中,你沒有約束來表明「name」是唯一的。也許從您的視圖傳回的 ID是安全
  • 理想情況下,你應該處理查找具有自定義屬性編輯器 - 這裏有一個例子:Grails command object data binding

不管怎麼說,希望幫助。

+0

拯救生命:-)我已經解決了問題的一部分解決方案,但是這真的幫助我解決了另一個問題:-D – user723858

+0

最佳答案...以及對問題的良好解釋 –

1

力圖把雙向依賴於對方

class Areas { 

    String name 
    static belongsTo = [User] 
    static hasMany = [users:User] 
} 

不要忘了從用戶

1
class Areas { 
    String name 
    static belongsTo = [User] 
    static hasMany = [users:User] 
} 
相關問題