Reputation: 260
I have three entities. Both ResolvedCorpus
and UnqualifiedCorpus
are subclasses of Corpus
to help model and address certain concerns for some Corpus
.
Joined inheritance type is selected for data persistence via JPA. The entities are defined as below.
@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 {}
With @OnDelete
annotation specified, I want to achieve the follows:
ResolvedCorpus
gets deleted via repository.delete()
, the corresponding Corpus
is deleted as well in Table corpus
;UnqualifiedCorpus
gets deleted via repository.delete()
, the corresponding Corpus
is remained.However, @OnDelete
does not work as expected. BTW, H2 is used as the embedded DB.
The testing code is copied below.
//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);
And you can find the testing application here.
I diagnosed the DDL for table creation and row deletion. I suspect the @OnDelete
is aiming to do the opposite, which means it controls how sub-entity shall behave when the base entity object gets deleted. when calling repository.delete(Resolved)
, the DDL generated is delete from corpus
instead of delete from resolved_corpus
; and for Unqualified
, both delete from unqualified
and delete from corpus
are called in order.
I guess, the request like I have should be a reasonable feature expected from JPA, but I cannot find a proper solution after some search online.
Upvotes: 1
Views: 792