2012-05-07 49 views
0

当我更改我网站上某条内容的“所有者”时,出现如下所示的错误。我很困惑,为什么我得到这个错误。看起来好像它试图改变项目本身的ID。一切看起来都是正确的...我在寻找所有正确的地方吗?无法保存实体更改:实例的标识已被更改

错误

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

我的JSP

当我改变owner.idowner我得到一个字符串/整数不匹配。

 <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; 

回答

1

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

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

在窗体上,结合“拥有者”,而不是“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)); 
} 

然后你犯了一个类,告诉春如何把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); 
    } 

} 
+0

我感谢所有的努力......但看起来这应该是简单 – Webnet

+0

还有其他的方式,他们有各种各样的上涨和下跌。我建议这一点,因为它很容易理解,并且在不依赖服务器端状态的情况下展示最少的潜在漏洞。记住,你只需要定义属性编辑器一次,然后在绑定用户的任何控制器中作为一个“简单”方法。您可以在技术上将编辑器设置为WebDataBinder的默认配置,并且绝不会向控制器添加任何内容,但我建议不要为Entity类个人做这些。 – Affe

+0

感谢您的快速回复:) – Webnet