2014-04-13 97 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