我有一个
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.addBar(bar); // adds it bidirectionally
barRepository.save(bar); // JpaRepository
但是当我想再次从foo中删除相同的条时,使用
foo.removeBar(bar); // removes it bidirectionally
barRepository.save(bar); // JpaRepository
通过调试我看到
foo.removeBar(bar);
我做错什么了吗?
我很确定这与级联选项有关,因为我只保存了条。
我尝试过:
-
orphanRemoval = true
在两个@OneToMany-annotations上,这都不起作用。我认为这是正确的,因为我不知道
既不是Foo也不是Bar,只是他们的关系。
-
从@OneToMany注释中排除CascadeType.REMOVE,但与orninremove相同,我认为这不适用于这种情况。
编辑:
我怀疑在我的代码或模型中一定有什么东西干扰了我的删除,因为现在已经有两个答案说它可以工作(与
orphanRemoval=true
).
原来的问题已经回答,但如果有人知道什么可能导致我的孤儿搬迁不工作,我将非常感谢你的意见。谢谢
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
}