【问题标题】:object is an unsaved transient instance - save the transient instance before mergingobject 是一个未保存的瞬态实例 - 在合并之前保存瞬态实例
【发布时间】:2012-06-21 17:25:48
【问题描述】:

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

显然,当您从下拉列表中选择并尝试保存 Appartment 时,我的应用程序认为 Person 已被修改。它给了我下面的错误,表明我应该先保存这个人。但是 Person 没有被修改。只有 Appartment 应该与对不同 Person 的引用一起保存。

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

我怎样才能让我的应用程序明白 Person 本身没有被修改。只有公寓?

这是我的代码:

@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" />

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

更新: Steven 建议我从 appartment.clientResponsiblePerson.id 中删除 id。这是一个合理的建议。我只是尝试过,但似乎我的应用程序不知道如何将表单提交的值映射到个人对象。当我设置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 引用没有设置为自动持久或合并。

让我感到震惊的是,我想要实现的目标应该是直截了当的。什么是我没有到达这里?

【问题讨论】:

  • 您作为更新的一部分发布的消息意味着传递给列表属性 (responsiblePersons) 的值不是“集合/数组/映射/枚举/迭代器”。除非您更改了操作的 getResponsiblePersons() 方法或更改了 s:select 标记上的 list 属性的值,否则您不应该收到该错误。

标签: java hibernate struts2


【解决方案1】:

显然,当您从下拉列表中选择并尝试保存 Appartment 时,我的应用程序认为 Person 已被修改。

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

appartment.clientResponsiblePerson.id

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

尝试改用appartment.clientResponsiblePerson,看看它对你有什么作用。

更新

另外一件很奇怪的事情是,我以另一种形式做同样的事情。

我也不明白这会如何工作。

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

  1. 创建一个类型转换器来告诉 Struts2 如何将“1”(或从下拉列表中传入的任何内容)转换为 Person 的实例。
  2. 在您的操作中添加setPerson(Integer) 方法,该方法将根据传入的整数主键查找适当的 Person 实体,然后将您的 s:select 更新为 &lt;s:select name="person" list="responsiblePersons" .../&gt;

就个人而言,我使用#1。

【讨论】:

  • 感谢您的回答。刚试了一下,它又给我带来了另一个新错误。有关详细信息,请参阅我的更新答案。
  • 请为您的 s:select 提供更新后的代码。您仍然需要 listKey 和 listValue,它们驱动下拉列表中的内容,与 Struts2 在后端所做的无关。
  • 感谢史蒂文的更新。只要我有时间并发布结果,我就会试一试。但我认为你只是给了我我所缺少的解决方案 :) 不知道为什么其他形式虽然有效.. 但那是一个不同的故事。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-04
  • 2012-11-08
  • 2015-09-27
  • 2021-03-03
  • 2013-11-30
  • 2017-04-12
相关资源
最近更新 更多