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

时间:2016-11-04 14:28:38

标签: java jpa entity eclipselink

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

  1. 细分关系
  2. 更新所有者实体
  3. 删除实体
  4. 但现在我的主键是关系的一部分,所以这是不可能的。

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

    我试图将“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)与主键相同(或应该是)

    在找到实际解决方案之前,这可能会帮助有相同问题的人。

1 个答案:

答案 0 :(得分:1)

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

问题是您有两个具有双向关系的实体。如果更改关系(例如将其清空),则需要将此更改合并到上下文中。因此,要删除OrderBill实例,必须在实例上调用em.remove以及将OrderWeek引用置空,并在OrderWeek上调用merge。这需要在同一个事务中完成,虽然对OrderWeek的orderBill引用的更改是数据库中的no-op,但它会保持缓存不同并阻止OrderBill复活(或者你是例外)看到)

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