Java 复合实体的更新失败
我有一个人实体,它与位置实体构成Java 复合实体的更新失败,java,hibernate,Java,Hibernate,我有一个人实体,它与位置实体构成 @ManyToOne(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE }) @Cascade( {org.hibernate.annotations.CascadeType.SAVE_UPDATE }) public Location getLocation() { return location; } 位置实体的名称为Id @Id public S
@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;
}
在SpringMVC表单中,当Person的位置从L1更改为L2时,我遇到以下异常,其中Person实体是表单的modelAttribute
org.springframework.orm.hibernate3.HibernateSystemException:com.x.y.z.Location实例的标识符从L2更改为L1;嵌套异常是org.hibernate.HibernateException:com.x.y.z.Location实例的标识符从L2更改为L1
你把我搞糊涂了
您映射的是一个关联;Hibernate(JPA)中的合成通过@Embedded
/@Embedded
注释进行映射。关联是独立实体之间的关系;它们通常通过实体标识符(数据库中的外键)连接
在您的特定情况下,Person
实体指向Location
实体,这意味着在数据库PERSONS
表中有一个Location\u ID
外键(名称可能不同)指向LOCATIONS
表。您试图做的是更新位置
端上的键,这是非法的,因为它会切断Hibernate的关系(另一端仍然在内部保留以前的键值)
主键通常应该是代理键,并且一开始就不可更新;如果您确实需要“更新”它,您必须将位置
与人员
解除关联,更新位置
并再次将其分配给人员
,或者创建一个全新的位置
实例并将其分配给您的人员
综上所述,如果您真的试图对组合关系建模,您需要将@ManyToOne替换为@Embedded,并相应地更改您的表模式。这里有一个链接到
Hibernate注释文档
另外,在两个单独的注释(JPA和Hibernate扩展)中指定级联类型也不是一件好事。如果您真的需要Hibernate扩展(在本例中不需要),只需使用它,并将JPA注释中的
cascade
属性保留为空。我在独立应用程序中也做了同样的事情。这东西行得通。我认为@modeldattribute应该有问题 在您的位置中,模型类中的实体属性id类型已更改。请参阅id和映射属性id类型相同。请确保id属性getter和setter函数返回类型。