Может кто-нибудь объяснить orphanRemoval в Hibernate? - PullRequest
0 голосов
/ 07 апреля 2019

Мой вопрос не в том, как работает "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» остается.

что я делаю не так? или это правильное поведение?

1 Ответ

1 голос
/ 09 апреля 2019

removeOrphan удаляет элемент из базы данных, когда он больше не связан с родителем. Это работает только при удалении элемента из списка в том же сеансе. Примечание: удаление из списка и удаление ссылки из элемента на родительский объект - это две разные вещи, даже если вы (должны) использовать один и тот же внешний ключ в базе данных для этих двух ссылок.

Примечание. Не работает, когда вы удаляете элемент из одного списка и добавляете его в другой. Когда вам везет, вы получаете исключение, которое говорит вам, что оно не работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...