java - 复合实体的更新失败

标签 java hibernate

我有 Person 实体,它与 Location 实体组合

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

当 Person 的位置在 Spring MVC 表单中从 L1 更改为 L2 时,我收到以下异常,其中此 Person 实体是表单的 modelAttribute。

org.springframework.orm.hibernate3.HibernateSystemException:identifier of an instance of com.x.y.z.Location was altered from L2 to L1; nested exception is org.hibernate.HibernateException: identifier of an instance of com.x.y.z.Location was altered from L2 to L1

最佳答案

你很困惑CompositionAssociation .

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

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

主键通常应该是代理键并且一开始就不可更新;如果您确实需要“更新”它,则必须取消 LocationPerson 的关联,更新 Location 并将其分配给 再次 Person 或创建一个全新的 Location 实例并将其分配给您的 Person

总而言之,如果您确实尝试对组合关系进行建模,则需要将 @ManyToOne 替换为 @Embedded 并相应地更改表架构。这是一个链接 关于 mapping components 的 Hibernate 注解文档.

此外,在两个单独的注释(JPA 与 Hibernate 扩展)中指定级联类型也不是一件好事。如果您确实需要 Hibernate 扩展(在本例中您不需要),只需使用它并将 JPA 注释中的 cascade 属性留空即可。

关于java - 复合实体的更新失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1341889/

相关文章:

Java 应用服务器;哪个更好?

java - 插入两个不同数据库中的两个表

java - hibernate 异常 "PropertyValueException: not-null property references a > null or transient value"。我被困住了,不知道该怎么办

java - 从 colors.xml 更改元素的颜色

java - 将同一数据库中的多行映射到单个实体

java - 如何在 spring hibernate 中加入表

java - 通过两个不同的 JVM 进程异常分隔 Hibernate 实例

java - Java 中的窗口应用程序

java - for-each 数组操作

java - Java 中的静态和非静态初始化 block