我有Person实体,其中包含Location Entity
的组合@ManyToOne(fetch = FetchType.EAGER, cascade =
{ CascadeType.PERSIST, CascadeType.MERGE })
@Cascade(
{org.hibernate.annotations.CascadeType.SAVE_UPDATE })
public Location getLocation()
{
return location;
}
位置实体的名称为ID
@Id
public String getName()
{
return name;
}
当Spring的MVC表单中Person的位置从L1更改为L2时,我得到以下Exception,其中此Person实体是表单的modelAttribute。
org.springframework.orm.hibernate3.HibernateSystemException:com.x.y.z.Location实例的标识符从L2更改为L1;嵌套异常是org.hibernate.HibernateException:com.x.y.z.Location实例的标识符从L2更改为L1
答案 0 :(得分:3)
您将Composition与Association混淆。
你所映射的是一个联想; Hibernate(JPA)中的组合通过@Embeddable
/ @Embedded
注释进行映射。关联是不同实体之间的关系;它们通常通过实体标识符(数据库中的外键)连接。
在您的特定情况下,Person
实体指向Location
实体,这意味着在数据库PERSONS
表中有一个LOCATION_ID
外键(名称可能不同)到{{ 1}}表。您要做的是在LOCATIONS
端更新该密钥,这是非法的,因为它会切断Hibernate的关系(另一端仍然保留内部的先前密钥值)。
主键通常应该是代理,而不是可更新的;如果您确实需要“更新”它,则必须将Location
与Location
取消关联,更新Person
并再次将其分配给Location
或创建一个全新的Person
{1}}实例并将其分配给您的Location
。
所有这一切,如果你真的想要建立Composition关系模型,你需要用@Embedded替换@ManyToOne并相应地更改你的表模式。这是一个链接 mapping components上的Hibernate Annotations文档。
此外,在两个单独的注释中指定级联类型(JPA与Hibernate扩展)并不是一件好事。如果你真的需要Hibernate扩展(在这种情况下你不需要),只需使用它并将JPA注释中的Person
属性留空。
答案 1 :(得分:0)
我在独立应用程序中做了同样的事情。事情有效。我认为这应该是@modelAttribute的一些问题。
答案 2 :(得分:0)
在您的位置实体属性中,类型已在模型类中更改。请参阅 id和映射属性ID类型相同。确保id属性< strong> getter和setter函数返回类型。