简体   繁体   中英

Can someone explain orphanRemoval in Hibernate?

My question is not how work "mappedBy". I know, just indicates the owner of the relation. My question is how orphanRemoval works. And in my case I don't use the indication mappedBy at all.

I have the following entities:

@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;
}

And I'm trying to test the functionality of removing orphans.

And I wrote the following test:

@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>

I don't understand the point at all "orphanRemoval = true". Why does he work like that? As a result, we only remove the link to "GoodOrphan" from the "CatalogOrphan", and the link from "GoodOrphan" to "CatalogOrphan" remains.

what am i doing wrong? or is this correct behavior?

removeOrphan removes an item from the database when it is not linked to a parent anymore. It only works when you remove the item from the list in the same session. Note: removing from the list and remove the reference from the item to the parent are two different things, even though you (should) use the same foreign key in the database for these two references.

Note: It doesn't work when you remove an item from one list and add it to another. When you are lucky, you get an exception that tells you that it doesn't work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM