无法保存实体更改:实例的标识符已更改

时间:2012-05-07 19:02:07

标签: java spring-mvc

当我更改网站上某段内容的“所有者”时,我收到的错误如下所示。我很困惑为什么我收到这个错误。似乎它正在尝试更改项目本身的ID。一切看起来都正确......我在寻找所有合适的地方吗?

错误

Caused by: org.hibernate.HibernateException: identifier of an instance of com.site.model.User was altered from 13 to 72

我的JSP

当我将owner.id更改为owner时,我得到字符串/整数不匹配。

        <label class="formLabel">Owner <img src="/images/s.gif" class="required"/><br/>
            <form:select path="owner.id" id="owner">
                <form:options items="${owners}" itemValue="id" />
            </form:select>
        </label>

我的服务

    Content cm = em.merge(content);
    em.flush();

内容模型

@NotNull
@JoinColumn(name = "owner_id", referencedColumnName = "id")
@ManyToOne
@IndexedEmbedded
@JsonIgnore
private User owner;

用户模型

@Id
@Basic(optional = false)
@Column(name = "id")
@GeneratedValue(strategy= GenerationType.IDENTITY)
@JsonIgnore
private Integer id;

2 个答案:

答案 0 :(得分:1)

你告诉spring要覆盖那里的User对象上的id字段,并从JSP中获取不同的id值。如果要更改所有者,则需要获取作为新所有者的整个User对象,并将引用更改为指向父记录上的引用。您不能只更改现有对象的ID号。

有很多方法可以实现这一点,通常使用PropertyEditor,因此您可以将数字直接绑定到值'owner',并提供一个类,告诉spring如何将数字转换为实例用户。

在表单上,​​绑定到“所有者”而不是“id”:

<form:select path="owner" id="owner">
  <form:options items="${owners}" itemValue="id" />
</form:select>

在控制器中,初始化属性编辑器:

@InitBinder
private void registerPropertyEditor(DataBinder binder) {
    binder.registerCustomEditor(User.class, "owner", new UserPropertyEditor(userService));
}

然后你创建一个类,告诉spring如何将ID号转换为用户:

public class UserPropertyEditor extends PropertyEditorSupport {

    private UserService userService;

    public UserPropertyEditor(UserService userService) {
        this.userService = userService;
    }

    @Override
    public String getAsText() {
        //Handle null value, value of incorrect type, etc here

        return String.valueOf(((User) getValue()).getId());
    }

    @Override
    public void setAsText(String id) throws IllegalArgumentException {
        //handle empty string, number format exception, etc

        User user = userService.getUser(integerId);

        setValue(user);
    }

}

答案 1 :(得分:0)

我也遇到这个问题。 就我而言,我无法在 sla 字段中输入数字 7。但是,如果我更改了 7 以外的值,则进程会正常运行。 出现的错误信息如 .... was altered from 7 to null

我尝试了很多方法,例如将类型数据从Integer更改为Long,创建新模型,但问题仍然存在。

直到我更改模型的属性之一,例如:

@Column(name = "sla")
private String sla;

到:

@Column(name = "sla")
private String slavalue;

薇奥拉,问题解决了