object是未保存的瞬态实例 - 在合并之前保存瞬态实例

时间:2012-06-21 17:25:49

标签: java hibernate struts2

我有一个表单来添加新的公寓,在这个表单中我有一个下拉列表,用户可以选择负责人。

当您从下拉列表中选择并尝试保存公寓时,我的应用程序会认为人员已被修改。它给了我下面的错误,表明我应该先保存Person。但是人没有被修改。只有公寓才能保存,并提及不同的人。

object is an unsaved transient instance - save the transient instance before merging

如何让我的应用程序了解此人本身未被修改。只有公寓?

这是我的代码:

@Entity
@Table(name = "Person")
public class Person{
    @Id
    private Long id;
    private String fullName;
    ....
}

@Entity
@Table(name = "Appartment")
public class Appartment{
    ....
    @ManyToOne (fetch = FetchType.LAZY)
    @JoinColumn (name = "client_contact_person_id")
    private Person clientResponsiblePerson;
}

该操作将所有人加载到List responsiblePersons中。

和JSP:

<s:select name="appartment.clientResponsiblePerson.id" list="responsiblePersons"
        listKey="id" listValue="fullName" headerKey="-1"
        label="%{getText('appartment.clientContact.ourContact')}" headerValue="%{getText('person.choose')}"
        required="true" cssClass="select medium" />

有什么想法吗?我一直在搜索和调试几个小时没有任何解决方案...... :(

更新: 史蒂文建议我从appartment.clientResponsiblePerson.id中删除ID。这是一个合理的建议。我只是试了一下,但是看起来我的应用程序似乎不知道如何将表单提交的值映射到Person-object。在设置listKey="id"时,提交的值是人员ID。

我收到以下错误: Invalid field value for field "appartment.clientResponsiblePerson".

tag 'select', field 'list', name 'appartment.clientResponsiblePerson': The requested list key 'responsiblePeople' could not be resolved as a collection/array/map/enumeration/iterator type. Example: people or people.{name} - [unknown location]

所以我最初的想法是,我应该从我的s:select中删除listKey和listValue。也许struts自动检测对象的id并使用toString作为值?但我也试过这个,没有更多的运气。

另一个非常奇怪的事情是我以另一种形式做同样的事情。在那种形式中,我从下拉列表中选择区域。我正在使用appartment.area.id作为名称。它在那里完美运作。奇怪..我还检查过Area - Appartment引用没有设置为自动持久化或合并。

令我感到震惊的是,我想要实现的目标应该是非常直截了当的。我到底在这里是什么东西?

1 个答案:

答案 0 :(得分:1)

  

当您从下拉列表中选择并尝试保存公寓时,我的应用程序会认为人员已被修改。

这正是您的代码正在做的事情。以下行是罪魁祸首:

appartment.clientResponsiblePerson.id

这告诉Struts2框架获取您在下拉列表中选择的人的ID并将其传递给getAppartment().getClientResponsiblePerson().setId(id)。这不会改变为新的负责人,它会改变现有人的主键。调用setClientResponsiblePerson(Person)会改变此人。

尝试使用appartment.clientResponsiblePerson,看看它是如何运作的。

<强>更新

  

另一个非常奇怪的事情是我以另一种形式做同样的事情。

我不知道那是怎么回事。

Struts2不知道Person是什么,所以你有几个选择:

  1. 创建一个类型转换器,告诉Struts2如何将“1”(或从您的下拉列表中传入的任何内容)转换为Person的实例。
  2. 在您的操作上添加setPerson(Integer)方法,该方法将根据传入的Integer主键查找相应的Person实体,然后更新您的s:select to <s:select name="person" list="responsiblePersons" .../>
  3. 就个人而言,我使用#1。