I am encountering a problem when trying to implement a mixed inheritance strategy using JPA. The same behaviour is observed (two inserts - one for each subclass level) when using Hibernate 5.2.18 (JPA 2.1), 5.3.5 (JPA 2.2), and 5.4.22 (JPA 2.2).
I believe my implementation is inline with what is suggested in these threads but perhaps there is a subtlety I have missed:
- How to mix inheritance strategies with JPA annotations and Hibernate?
- Mapping multi-Level inheritance in Hibernate with Annotations
@Entity
@Table(name = "TABLE_A")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
abstract class A {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
public void setId(long id) {
this.id = id;
}
public long getId() {
return id;
}
}
@Entity
@SecondaryTable(name = "TABLE_B")
@DiscriminatorValue("B")
class B extends A {
@Column(table = "TABLE_B")
private String property1;
public String getProperty1() {
return property1;
}
public void setProperty1(String property1) {
this.property1 = property1;
}
}
@Entity
@SecondaryTable(name = "TABLE_B")
@DiscriminatorValue("C")
class C extends B {
@Column(table = "TABLE_B")
private String property2;
public String getProperty2() {
return property2;
}
public void setProperty2(String property2) {
this.property2 = property2;
}
}
An attempt to persist (insert) an objet of type C
results in hibernate attempting to perform two inserts into TABLE_B
:
insert into TABLE_A (id, DTYPE) values (null, 'C')
Natively generated identity: 2
insert into TABLE_B (property1, id) values (?, ?)
binding parameter [1] as [VARCHAR] - [foo]
binding parameter [2] as [BIGINT] - [2]
insert into TABLE_B (property2, id) values (?, ?)
binding parameter [1] as [VARCHAR] - [bar]
binding parameter [2] as [BIGINT] - [2]
could not execute statement [n/a]
org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: Unique index or primary key violation: "PRIMARY KEY ON TABLE_B(ID) [2, 'foo', NULL]";
Finally, if I change B
to be a @MappedSuperclass
instead of an @Entity
, I am able to persist a C
object correctly but this changes semantics and I can no longer persist B
objects as they are no longer entities in their own right.
Thanks,
EDIT:
Here is my DDL:
CREATE TABLE TABLE_A (
ID BIGINT IDENTITY NOT NULL PRIMARY KEY,
DTYPE VARCHAR(16) NOT NULL
);
CREATE TABLE TABLE_B (
ID BIGINT IDENTITY NOT NULL PRIMARY KEY,
PROPERTY1 VARCHAR(32),
PROPERTY2 VARCHAR(32),
CONSTRAINT FK_TABLE_B_PARENT FOREIGN KEY (ID) REFERENCES TABLE_A (ID)
);
I would attach an ER diagram but, as this is my first post, I don't have the minimal reputation which would allow me to do so.