我总是被告知,如果是双向关系,您可以按如下方式删除您的实体:
但现在我的主键是关系的一部分,所以这是不可能的。
在这种情况下,有没有人知道如何使用主外键删除实体?
我试图将“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)与主键相同(或应该是)
在找到实际解决方案之前,这可能会帮助有相同问题的人。
答案 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。