Kas*_*rer 6 java hibernate jpa cascade hibernate-onetomany
我和Many-to-Many班级之间有关系.因为我想获得有关辅助表的其他信息,所以我必须创建一个帮助类,如下所述:使用JPA和Hibernate时,使用额外列映射多对多关联的最佳方法FooBarFooBar
我创建了一个Foo,并创建了一些条形图(保存到DB).当我然后使用其中一个条添加到foo
foo.addBar(bar); // adds it bidirectionally
barRepository.save(bar); // JpaRepository
Run Code Online (Sandbox Code Playgroud)
然后创建FooBar的DB条目 - 正如预期的那样.
但是,当我想再次从foo中删除相同的栏时,使用
foo.removeBar(bar); // removes it bidirectionally
barRepository.save(bar); // JpaRepository
Run Code Online (Sandbox Code Playgroud)
然后,不会从数据库中删除先前创建的FooBar条目.通过调试,我看到foo.removeBar(bar);确实删除了双向.没有异常被抛出.
难道我做错了什么?我很确定它与Cascading选项有关,因为我只保存吧.
我尝试过的:
添加orphanRemoval = true@OneToMany - 注释,但没有用.我认为这是正确的,因为我不删除 Foo和Bar,只删除他们的关系.
从@OneToMany注释中排除CascadeType.REMOVE,但与orphanRemoval相同我认为这不适用于这种情况.
编辑: 我怀疑在我的代码或模型中必须有一些东西与我的orphanRemoval混淆,因为现在已有2个答案说它有效(带orphanRemoval=true).
最初的问题已得到解答,但如果有人知道什么可能导致我的孤儿无法工作,我会非常感谢您的意见.谢谢
代码: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);
}
}
Run Code Online (Sandbox Code Playgroud)
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;
}
}
Run Code Online (Sandbox Code Playgroud)
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
}
Run Code Online (Sandbox Code Playgroud)
我从示例代码中尝试了这一点。通过一些“草图”,重现了该错误。
不过,该解决方案确实很简单,只需添加orphanRemoval = true您提到的内容即可。在Foo.getFooBars():
@OneToMany(cascade = CascadeType.ALL, mappedBy = "foo", fetch = FetchType.EAGER, orphanRemoval = true)
public Collection<FooBar> getFooBars() {
return fooBars;
}
Run Code Online (Sandbox Code Playgroud)
将复制品发布到GitHub似乎是最简单的- 希望那里有进一步的细微差别或我错过的东西。
这是基于 Spring Boot 和 H2 内存数据库,因此不应在其他环境下工作 -mvn clean test如果有疑问,请尝试。
班级FooRepositoryTest有测试用例。它具有删除链接的验证FooBar,或者可能更容易读取记录的 SQL。
编辑
| 归档时间: |
|
| 查看次数: |
155 次 |
| 最近记录: |