Мой вопрос не в том, как работает «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". Почему он так работает? В результате мы убираем только ссылку на "GoodOrphan" из "CatalogOrphan", а ссылка с "GoodOrphan" на "CatalogOrphan" остается.
Что я делаю неправильно? или это правильное поведение?
@crizzis спасибо за комментарий. Но нет, на мой вопрос нет ответа.
removeOrphan удаляет элемент из базы данных, когда он больше не связан с родителем. Это работает только тогда, когда вы удаляете элемент из списка в том же сеансе. Примечание: удаление из списка и удаление ссылки из элемента на родителя — это две разные вещи, хотя вы (должны) использовать один и тот же внешний ключ в базе данных для этих двух ссылок.
Примечание. Это не работает, когда вы удаляете элемент из одного списка и добавляете его в другой. Когда вам повезет, вы получите исключение, которое говорит вам, что это не работает.
Возможный дубликат Может кто-нибудь объяснить mappedBy в спящем режиме?