假设您有从A类到B类的单向一对多关联,如下所示:
public class A {
@OneToMany(cascade = CascadeType.ALL)
private List<B> myBs;
}
public class B {
//I know nothing about A
}
在数据库中,这些是通过第三个表连接,保持其ID。
现在,我想删除一个连接到A的B对象.A有自己的存储库类,B有自己的存储库类。
在我的项目的类似设置中完成此操作的方法是首先要求有问题的A删除有问题的B,然后告诉EnitityManager
从数据库中删除B。
这使我在两个选择之间陷入困境,在我看来它们都不是最佳选择:
BRepository
中的存储库方法处理从连接到的A中删除B,以及通过EntityManager
从数据库中删除。我不喜欢这个,因为B的存储库类必须操纵A对象。
BRepository中的存储库方法仅处理通过EntityManager的删除,将其留给调用者将其从A的集合中删除。我更喜欢这个,因为如果有人在没有先从A的集合中删除B的情况下调用存储库,它将会失败。
在这两个中,我发现第一个是迄今为止最好的。但是,我真的不认为它很干净。
Hibernate中是否有一些构造允许删除项目从数据库中删除后从其所属的任何集合中删除? (试图删除B失败,因为包含它的A也被加载到同一个事务中,所以它在事务结束时失败,当它试图存储被删除的东西时。)
(在A中mappedBy
添加@OneToMany-mapping
会解决问题吗?)
答案 0 :(得分:3)
通过使用孤儿删除,我找到了解决这个问题的方法。
通过将A中的映射更改为:
public class A {
@OneToMany(cascade = CascadeType.ALL)
@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
private List<B> myBs;
}
我可以说
a.getMyBs().remove(b);
和b
将在a
被保留后删除。
答案 1 :(得分:2)
走出Hibernate思维模式之外,问自己:谁拥有B
s?
业主最终对其财产负责。通常情况下,如果没有B
的{{1}}且每个A
仅由一个B
所拥有,则情况属实。
因此,如果A
拥有A
s,则B
负责清除ARepository
。我会在B
中创建一个方法来执行清理,并在ARepository
中调用delete方法。
答案 2 :(得分:0)
如果您确实希望将存储库分开,则另一个选项是在顶部创建一个知道两者的服务类,并以与您的选项1方法类似的方式处理您的删除。
(在A中的@ OneToMany-mapping上添加mappedBy会解决问题 问题?)
我认为这取决于他的存储库实现。对于JPA EntityManager,如果会话已关闭,当您删除B时,即使它是双向映射,也会分离。