复合实体的更新失败

时间:2009-08-27 15:37:02

标签: java hibernate

我有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

3 个答案:

答案 0 :(得分:3)

您将CompositionAssociation混淆。

你所映射的是一个联想; Hibernate(JPA)中的组合通过@Embeddable / @Embedded注释进行映射。关联是不同实体之间的关系;它们通常通过实体标识符(数据库中的外键)连接。

在您的特定情况下,Person实体指向Location实体,这意味着在数据库PERSONS表中有一个LOCATION_ID外键(名称可能不同)到{{ 1}}表。您要做的是在LOCATIONS端更新该密钥,这是非法的,因为它会切断Hibernate的关系(另一端仍然保留内部的先前密钥值)。

主键通常应该是代理,而不是可更新的;如果您确实需要“更新”它,则必须将LocationLocation取消关联,更新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函数返回类型。