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


细分关系
更新所有者实体
移除实体


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

在这种情况下,是否有人知道如何使用主外键删除实体?

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

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


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

此处的类OrderBill具有指向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类)来解决此问题。现在,我可以在不触摸外键的情况下中断关系。

此“解决方案”仍然不理想:OrderWeek现在具有一个冗余列(例如,weekNr2和yearNr2),该列(或应该)与主键相同

也许这会帮助有相同问题的人找到实际的解决方案。

最佳答案

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

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

另一种方法是将孤立删除标记添加到OrderWeek的orderBill属性中,如果您将此引用无效,JPA将自动调用em.remove。

关于java - 如何在JPA中删除带有外键的对象?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40425179/

10-10 00:17