首页 > 解决方案 > 如何禁用 JPA 加入继承实体的删除级联?

问题描述

我有三个实体。两者ResolvedCorpusUnqualifiedCorpus都是Corpus帮助建模和解决某些问题的子类Corpus

通过 JPA 为数据持久性选择联合继承类型。实体定义如下。

@Entity
@Table(name="corpus")
@Inheritance(strategy = InheritanceType.JOINED)
public class Corpus implements Serializable  {}

@Entity
@Table(name = "resolved_corpus")
@OnDelete(action=OnDeleteAction.CASCADE)
public class ResolvedCorpus extends Corpus {}

@Entity
@Table(name="unqualified_corpus")
@OnDelete(action=OnDeleteAction.NO_ACTION)
public class UnqualifiedCorpus extends Corpus {}

指定注释后,@OnDelete我想实现以下目标:

  1. ResolvedCorpus通过 删除 a 时repository.delete(),对应Corpus的也会在 Table 中删除corpus
  2. 当 aUnqualifiedCorpus通过 被删除时repository.delete(),对应Corpus的将保留。

但是,@OnDelete不能按预期工作。顺便说一句,H2 用作嵌入式数据库。

测试代码复制如下。

        //create corpora, one for each type: normal, resolved, unqualified.
        Corpus normal = new Corpus();
        normal.setName("normal");
        corpusRepository.save(normal);

        ResolvedCorpus resolved = new ResolvedCorpus();
        resolved.setName("resolved");
        resolved.setResolved("resolved");
        resolvedCorpusRepository.save(resolved);

        UnqualifiedCorpus unqualified = new UnqualifiedCorpus();
        unqualified.setName("unqualified");
        unqualified.setReason("unqualified");
        unqualifiedCorpusRepository.save(unqualified);

        //query
        // 3 records are expected in corpus table
        // 1 record in resolved table
        // 1 in unqualified table
        assertTrue(corpusRepository.count() == 3);
        assertTrue(resolvedCorpusRepository.count() == 1);
        assertTrue(unqualifiedCorpusRepository.count() == 1);
        resolvedCorpusRepository.findAll().forEach((item) -> {
            assertTrue(item.getName().equals("resolved"));
        });
        unqualifiedCorpusRepository.findAll().forEach((item) -> {
            assertTrue(item.getName().equals("unqualified"));
        });

        //delete
        // when deleting resolved, the delete action is expected to get cascaded to ancestor table "corpus", as OnDeleteAction suggested.
        // when deleting unqualified, the delete action is not expected to get cascaded to ancestor table "corpus", as OnDeleteAction suggested.
        resolvedCorpusRepository.deleteAll();
        unqualifiedCorpusRepository.deleteAll();
        //query
        //HOWEVER, OnDeleteAction.NO_ACTION is NOT working as expected, and this assertion is failed.
        assertTrue(corpusRepository.count() == 2);

您可以在此处找到测试应用程序。

我诊断了用于表创建和行删除的 DDL。我怀疑它@OnDelete的目的是相反的,这意味着它控制子实体在基础实体对象被删除时的行为方式。调用时repository.delete(Resolved),生成的 DDLdelete from corpus不是delete from resolved_corpus; 和 for Unqualifieddelete from unqualifieddelete from corpus都按顺序调用。

我想,像我这样的请求应该是 JPA 期望的合理功能,但是在网上搜索后我找不到合适的解决方案。

标签: javahibernatejpahibernate-cascadenhibernate-inheritance

解决方案


推荐阅读