如何在 JPA 中删除具有外部主键的对象?

How can I remove an object with a foreign primary key in JPA?

我总是被告知,在双向关系的情况下,您可以按如下方式删除您的实体:

  1. 关系破裂
  2. 更新所有者实体
  3. 删除实体

但现在我的主键是关系的一部分,所以这不再可能了。

有人知道在这种情况下如何删除具有主外键的实体吗?

我尝试将 "mappedby" 属性 设置为 null 而不仅仅是调用 manager.remove(...),但总有另一个实体管理器仍然有一个已删除实体的托管实例,因此出现以下错误:

During synchronization a new object was found through a relationship
that was not marked cascade PERSIST

下面我放了我正在使用的 classes 的代码。

这里的classOrderBill有指向OrderWeek的主外键。这个主键也是一个组合键,遗憾的是代码的可读性有点差,但它不应该对我遇到的问题有任何影响。

public class OrderBill{
        @EmbeddedId
        private OrderWeekPK orderWeekPK;

        @OneToOne
        @JoinColumns(value = {
            @JoinColumn(name="weekNr", referencedColumnName = "weekNr"),
            @JoinColumn(name="yearNr", referencedColumnName = "yearNr")})
        @MapsId
        private OrderWeek orderWeek;
    }

public class OrderWeek{
    @OneToOne(mappedBy="orderWeek")
    private OrderBill orderBill;

    @EmbeddedId
    private OrderWeekPK orderWeekPK;
}

@Embeddable
public class OrderWeekPK implements Serializable{
    @Column(name="yearNr")
    private int yearNr;
    @Column(name="weekNr")
    private int weekNr;
}

是否有我缺少的策略?

更新:现在我可以通过切换拥有方和被拥有方来规避这个问题(将mappedby转移到OrderBill class)。现在我可以在不触及外主键的情况下打破关系。

这个 "solution" 仍然不理想:OrderWeek 现在有一个冗余列(例如 weekNr2 和 yearNr2)与主键相同(或应该)

也许这可以帮助遇到相同问题的人,直到找到实际的解决方案。

您可以通过在 orderWeek 属性 上使用 @Id 并在实体上指定 @IdClass(OrderWeekPK.class) 来取消 @MapsId 并将其嵌入到 OrderBill 中 - 这可能适用于您的映射,但不是您在 post 中提到的错误的来源。

问题是您有两个具有双向关系的实体。如果您更改关系(例如将其取消),则需要将此更改合并到上下文中。因此,要删除 OrderBill 实例,您必须对该实例调用 em.remove 并清空 OrderWeek 引用,然后在 OrderWeek 上调用 merge。这需要在同一个事务中完成,虽然对 OrderWeek 的 orderBill 引用的更改是数据库中的空操作,但它将保持缓存不同步并防止 OrderBill 被复活(或您看到的异常)

另一种方法是将孤立删除标记添加到 OrderWeek 的 orderBill 属性,这会导致 JPA 在您取消此引用时自动调用 em.remove。