有人可以解释 Hibernate 中的 orphanRemoval 吗?
Can someone explain orphanRemoval in Hibernate?
我的问题不是如何工作 "mappedBy"。我知道,只是表示关系的所有者。我的问题是 orphanRemoval 是如何工作的。
在我的例子中,我根本不使用指示 mappedBy。
我有以下实体:
@Entity
@Table(name = "catalog_orphan")
public class CatalogOrphan extends AbstractBaseEntity<Long> {
@OneToMany(orphanRemoval = true)
private List<GoodOrphan> goodOrphans;
public List<GoodOrphan> getGoodOrphans() {
return goodOrphans;
}
public void setGoodOrphans(List<GoodOrphan> goodOrphans) {
this.goodOrphans = goodOrphans;
}
}
@Entity
@Table(name = "good_orphan")
public class GoodOrphan extends AbstractBaseEntity<Long> {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "catalog_orphan_id")
private CatalogOrphan catalogOrphan;
public CatalogOrphan getCatalogOrphan() {
return catalogOrphan;
}
public void setCatalogOrphan(CatalogOrphan catalogOrphan) {
this.catalogOrphan = catalogOrphan;
}
}
@MappedSuperclass
public abstract class AbstractBaseEntity<ID> {
@Id
@Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected ID id;
@Column(name = "name")
protected String name;
}
我正在尝试测试删除孤儿的功能。
然后我写了下面的测试:
@RunWith(SpringRunner.class)
@DataJpaTest
@TestExecutionListeners({
TransactionalTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class,
DbUnitTestExecutionListener.class
})
@DatabaseSetup("/persistCascade/orphan/catalog_good_orphan.xml")
public class CatalogOrphanTest {
@Autowired
protected TestEntityManager entityManager;
@Test
public void clearCollections() {
CatalogOrphan catalog = entityManager.find(CatalogOrphan.class, 1L);
catalog.getGoodOrphans().clear();
entityManager.persist(catalog);
entityManager.flush();
entityManager.clear();
CatalogOrphan catalogAfterCleanCollection2 = entityManager.find(CatalogOrphan.class, 1L);
assertThat(catalogAfterCleanCollection2.getGoodOrphans().size(), equalTo(0)); // Does this mean that the connection has been deleted?
GoodOrphan goodOrphan = entityManager.find(GoodOrphan.class, 1L);
assertThat(goodOrphan.getCatalogOrphan(), is(notNullValue())); // WHY???
}
}
catalog_good_orphan.xml:
<dataset>
<Catalog_Orphan id="1" name="Catalog#1"/>
<Catalog_Orphan id="2" name="Catalog#2"/>
<Good_Orphan id="1" name="Good#1" catalog_orphan_id="1"/>
<Good_Orphan id="2" name="Good#2" catalog_orphan_id="1"/>
<Good_Orphan id="3" name="Good#3" catalog_orphan_id="2"/>
<Good_Orphan id="4" name="Good#4" catalog_orphan_id="2"/>
<!-- without catalog -->
<Good_Orphan id="5" name="Good#5" />
</dataset>
我完全不明白这一点"orphanRemoval = true"。
他为什么那样工作?结果,我们只去掉了"CatalogOrphan"中的link到"GoodOrphan",而"GoodOrphan"到"CatalogOrphan"中的link仍然存在。
我做错了什么?还是这是正确的行为?
removeOrphan 在不再链接到父级时从数据库中删除项目。它仅在您从同一会话的列表中删除项目时才有效。注意:从列表中移除和移除项目对父项的引用是两件不同的事情,即使您(应该)在数据库中对这两个引用使用相同的外键。
注意:当您从一个列表中删除一个项目并将其添加到另一个列表时,它不起作用。幸运的时候,你会得到一个异常,告诉你它不起作用。
我的问题不是如何工作 "mappedBy"。我知道,只是表示关系的所有者。我的问题是 orphanRemoval 是如何工作的。 在我的例子中,我根本不使用指示 mappedBy。
我有以下实体:
@Entity
@Table(name = "catalog_orphan")
public class CatalogOrphan extends AbstractBaseEntity<Long> {
@OneToMany(orphanRemoval = true)
private List<GoodOrphan> goodOrphans;
public List<GoodOrphan> getGoodOrphans() {
return goodOrphans;
}
public void setGoodOrphans(List<GoodOrphan> goodOrphans) {
this.goodOrphans = goodOrphans;
}
}
@Entity
@Table(name = "good_orphan")
public class GoodOrphan extends AbstractBaseEntity<Long> {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "catalog_orphan_id")
private CatalogOrphan catalogOrphan;
public CatalogOrphan getCatalogOrphan() {
return catalogOrphan;
}
public void setCatalogOrphan(CatalogOrphan catalogOrphan) {
this.catalogOrphan = catalogOrphan;
}
}
@MappedSuperclass
public abstract class AbstractBaseEntity<ID> {
@Id
@Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected ID id;
@Column(name = "name")
protected String name;
}
我正在尝试测试删除孤儿的功能。
然后我写了下面的测试:
@RunWith(SpringRunner.class)
@DataJpaTest
@TestExecutionListeners({
TransactionalTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class,
DbUnitTestExecutionListener.class
})
@DatabaseSetup("/persistCascade/orphan/catalog_good_orphan.xml")
public class CatalogOrphanTest {
@Autowired
protected TestEntityManager entityManager;
@Test
public void clearCollections() {
CatalogOrphan catalog = entityManager.find(CatalogOrphan.class, 1L);
catalog.getGoodOrphans().clear();
entityManager.persist(catalog);
entityManager.flush();
entityManager.clear();
CatalogOrphan catalogAfterCleanCollection2 = entityManager.find(CatalogOrphan.class, 1L);
assertThat(catalogAfterCleanCollection2.getGoodOrphans().size(), equalTo(0)); // Does this mean that the connection has been deleted?
GoodOrphan goodOrphan = entityManager.find(GoodOrphan.class, 1L);
assertThat(goodOrphan.getCatalogOrphan(), is(notNullValue())); // WHY???
}
}
catalog_good_orphan.xml:
<dataset>
<Catalog_Orphan id="1" name="Catalog#1"/>
<Catalog_Orphan id="2" name="Catalog#2"/>
<Good_Orphan id="1" name="Good#1" catalog_orphan_id="1"/>
<Good_Orphan id="2" name="Good#2" catalog_orphan_id="1"/>
<Good_Orphan id="3" name="Good#3" catalog_orphan_id="2"/>
<Good_Orphan id="4" name="Good#4" catalog_orphan_id="2"/>
<!-- without catalog -->
<Good_Orphan id="5" name="Good#5" />
</dataset>
我完全不明白这一点"orphanRemoval = true"。 他为什么那样工作?结果,我们只去掉了"CatalogOrphan"中的link到"GoodOrphan",而"GoodOrphan"到"CatalogOrphan"中的link仍然存在。
我做错了什么?还是这是正确的行为?
removeOrphan 在不再链接到父级时从数据库中删除项目。它仅在您从同一会话的列表中删除项目时才有效。注意:从列表中移除和移除项目对父项的引用是两件不同的事情,即使您(应该)在数据库中对这两个引用使用相同的外键。
注意:当您从一个列表中删除一个项目并将其添加到另一个列表时,它不起作用。幸运的时候,你会得到一个异常,告诉你它不起作用。