我在Many-to-Many
和Foo
类之间具有Bar
关系。因为我想在帮助程序表上获得更多信息,所以我不得不按如下说明制作一个帮助程序类FooBar
:The best way to map a many-to-many association with extra columns when using JPA and Hibernate
我创建了一个Foo,并创建了一些酒吧(保存到DB)。当我然后使用添加到foo的酒吧之一
foo.addBar(bar); // adds it bidirectionally
barRepository.save(bar); // JpaRepository
然后按预期创建FooBar的数据库条目。
但是当我想再次从foo中删除相同的栏时,使用
foo.removeBar(bar); // removes it bidirectionally
barRepository.save(bar); // JpaRepository
则会从数据库中删除先前创建的FooBar条目而不是。
通过调试,我看到
foo.removeBar(bar);
确实确实双向删除了。没有异常被抛出。难道我做错了什么?
我非常确定,这与级联选项有关,因为我只保存标准。
我尝试过的是:
orphanRemoval = true
-注释,该注释不起作用。我认为这是正确的,因为我既不删除Foo也不删除Bar,而是删除他们的关系。 编辑:我怀疑我的代码或模型中一定有与我的orphanRemoval混淆的东西,因为现在已经有2个回答说它可以工作(使用
orphanRemoval=true
)。最初的问题已得到解答,但是如果有人知道是什么原因导致我的orphanRemoval无法正常工作,我将非常感谢您的投入。谢谢
代码:Foo,Bar,FooBar
public class Foo {
private Collection<FooBar> fooBars = new HashSet<>();
// constructor omitted for brevity
@OneToMany(cascade = CascadeType.ALL, mappedBy = "foo", fetch = FetchType.EAGER)
public Collection<FooBar> getFooBars() {
return fooBars;
}
public void setFooBars(Collection<FooBar> fooBars) {
this.fooBars = fooBars;
}
// use this to maintain bidirectional integrity
public void addBar(Bar bar) {
FooBar fooBar = new FooBar(bar, this);
fooBars.add(fooBar);
bar.getFooBars().add(fooBar);
}
// use this to maintain bidirectional integrity
public void removeBar(Bar bar){
// I do not want to disclose the code for findFooBarFor(). It works 100%, and is not reloading data from DB
FooBar fooBar = findFooBarFor(bar, this);
fooBars.remove(fooBar);
bar.getFooBars().remove(fooBar);
}
}
public class Bar {
private Collection<FooBar> fooBars = new HashSet<>();
// constructor omitted for brevity
@OneToMany(fetch = FetchType.EAGER, mappedBy = "bar", cascade = CascadeType.ALL)
public Collection<FooBar> getFooBars() {
return fooBars;
}
public void setFooBars(Collection<FooBar> fooBars) {
this.fooBars = fooBars;
}
}
public class FooBar {
private FooBarId id; // embeddable class with foo and bar (only ids)
private Foo foo;
private Bar bar;
// this is why I had to use this helper class (FooBar),
// else I could have made a direct @ManyToMany between Foo and Bar
private Double additionalInformation;
public FooBar(Foo foo, Bar bar){
this.foo = foo;
this.bar = bar;
this.additionalInformation = .... // not important
this.id = new FooBarId(foo.getId(), bar.getId());
}
@EmbeddedId
public FooBarId getId(){
return id;
}
public void setId(FooBarId id){
this.id = id;
}
@ManyToOne
@MapsId("foo")
@JoinColumn(name = "fooid", referencedColumnName = "id")
public Foo getFoo() {
return foo;
}
public void setFoo(Foo foo) {
this.foo = foo;
}
@ManyToOne
@MapsId("bar")
@JoinColumn(name = "barid", referencedColumnName = "id")
public Bar getBar() {
return bar;
}
public void setBar(Bar bar) {
this.bar = bar;
}
// getter, setter for additionalInformation omitted for brevity
}
最佳答案
我从示例代码中进行了尝试。在两次“误入”之后,这重现了错误。
事实证明,该解决方案与添加您提到的orphanRemoval = true
一样简单。在Foo.getFooBars()
上:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "foo", fetch = FetchType.EAGER, orphanRemoval = true)
public Collection<FooBar> getFooBars() {
return fooBars;
}
将复制内容发布到GitHub似乎是最容易的-希望还有进一步的细微差别或我错过的地方。
它基于Spring Boot和H2内存数据库,因此不应在其他环境下工作-如有疑问,请尝试
mvn clean test
。FooRepositoryTest
类具有测试用例。它具有删除链接FooBar
的验证,或者可能更容易读取记录的SQL。编辑
这是下面的评论中提到的屏幕截图:
关于java - hibernate 多对多连接类级联问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52442803/