2014-04-13 67 views
2

我正在開發Grails 2.3.7應用程序,我無法通過選擇框更改域屬性。每次我嘗試更改屬性並保存時,我都會得到一個HibernateException: identifier of an instance of Ethnicity was altered from X to Y。我不想改變種族的身份,我只是想把種族從一個變成另一個種族。無法更改Grails中的域類屬性值

有幾件事情需要注意:我使用的是同一個控制器的動作來創建和更新的人

  1. 設置personInstance.ethnicitynullpersonInstance.properties = params前將保存的工作,但我 不知道爲什麼,我不想爲每個協會 ,我想改變這一點。
  2. 我意識到域模型似乎很奇怪。這是一個傳統的數據庫,我無法改變。

這裏是我的領域類:

class ApplicationPerson implements Serializable { 
    Integer appId 
    Integer applicationSequenceNumber 
    String firstName 
    String lastName 
    Ethnicity ethnicity 

    static mapping = { 
     id composite: ['appId', 'applicationSequenceNumber'], 
      generator: 'assigned' 
    } 
} 

class Ethnicity { 
    String code 
    String description 

    static mapping = { 
     id name: 'code', generator: 'assigned' 
    } 
} 

這是我_form.gsp更新Ethnicity(我刪除了所有正在保存就好了其他屬性):

<div class="fieldcontain ${hasErrors(bean: personInstance, 
            field: 'ethnicity', 'error')} "> 
    <label for="ethnicity">Ethnicity</label> 
    <g:select id="ethnicity" 
       name="ethnicity.code" 
       from="${Ethnicity.list()}" 
       optionKey="code" 
       value="${personInstance?.ethnicity?.code}" /> 
</div> 

最後一點,我的控制器動作表單POST:

def save() { 
    Application app = applicationService.getCurrentApplication() 

    // Find/Create and save Person 
    ApplicationPerson personInstance = app.person 
    if (!personInstance) { 
     personInstance = 
      new ApplicationPerson(appId: app.id, 
            applicationSequenceNumber: app.sequenceNumber) 
    } 
    personInstance.properties = params 

    if (!personInstance.validate()) { 
     respond personInstance.errors, view:'edit' 
     return 
    } 

    personInstance.save flush:true 
    redirect action: 'list' 
} 
+0

組合鍵中的'aidm'是什麼? – dmahapatro

+0

一個錯字。感謝您指出了這一點。 – grantmcconnaughey

+0

你使用遷移腳本嗎?以及如何備份後自動創建數據庫...? – danielad

回答

2

ethnicity.codeselect元件修改名稱到personInstance.etnicity.code,如下所示:

<g:select id="ethnicity" 
      name="personInstance.ethnicity.code" 
      from="${Ethnicity.list()}" 
      optionKey="code" 
      value="${personInstance?.ethnicity?.code}" /> 

選擇的選項的名稱被綁定到如params密鑰和所選擇的值作爲 value抵壓在鑰匙。使用ethnicity.code將嘗試修改現有ethnicity的主鍵,而不是修改應用人員的種族。

UPDATE
以上更名是可選的(情況下可以使用你不需要params被指定爲域類的屬性)。以前的名字ethnicity.code應以設置民族工作很好,但下面的變化也需要在控制器動作:

//or use params.ethnicity.code 
//if name is ethnicity.code 
person.ethnicity = Ethnicity.load(params.personInstance.ethnicity.code) 

//or use params if name is ethnicity.code 
person.properties = params.personInstance 

加載基於在code傳遞現有Ethnicity,然後將其設置爲person設置屬性之前。

問題在於codeEthnicity的主鍵。如果Ethnicity有一個單獨的標識列(例如,默認的長度爲id),那麼您確切的實現將在數據綁定的幫助下工作。但是由於提到您正在使用舊數據庫,我想您將無法修改表格以添加另一列id。所以你最好的選擇是從代碼中傳遞load(便宜,相比於從休眠緩存加載的行),然後將其設置爲人。

如果可能的話,您也可以看到嘗試緩存種族域,因爲這將是主數據和緩存的一個很好的候選者。

+0

我試過了,沒有任何運氣。我沒有我也試過'name =「applicationPerson.ethnicity.code」'沒有運氣。 ( – grantmcconnaughey

+0

)你是否得到相同的休眠錯誤? – dmahapatro

+0

不,當我做出這種改變時,它根本不會改變人的種族。有點像數據綁定沒有發生。我也發現執行'personInstance .ethnicity = null'就在'personInstance.properties = params'使一切正常工作。是否有可能映射我的域類錯誤?在DB中,'Person'表有一個'ethnicity_code'字段映射到'Ethnicity' ...所以我很確定我正確地映射了它 – grantmcconnaughey