Hello! Please ignore the weird model - it’s just to demonstrate.
I’m using Hibernate 6.6.45.
I have this discriminator-based embeddable hierarchy:
@Embeddable
@DiscriminatorColumn
public abstract class Car {
@Column(nullable = false)
private String color;
}
@Embeddable
@DiscriminatorValue("VW")
public class Volkswagen extends Car {
@Column
private Boolean electric;
}
@Embeddable
@DiscriminatorValue("TO")
public class Toyota extends Car {
@Column
private Integer numberOfWheels;
}
ParkingPlace supports different types of cars:
@Entity
public class ParkingPlace {
@Id
@GeneratedValue
private Long id;
@Embedded
private Car car;
}
But VolkswagenDealer references the Volkswagen type directly - my expectation is that this should work without having a discriminator column:
@Entity
public class VolkswagenDealer {
@Id
@GeneratedValue
private Long id;
@Embedded
private Volkswagen specialDeal;
}
Creating, persisting, reading ParkingPlace instances with different types of Car works perfectly.
But if I were to create and read back a VolkswagenDealer with its Volkswagen:
@Test
void terminalEmbeddableReferenceTest(SessionFactoryScope scope) throws Exception {
scope.inTransaction(session -> {
var pp = createVolkswagenDealer(session);
Assertions.assertNotNull(pp.getId());
session.flush();
session.refresh(pp);
Assertions.assertInstanceOf(Volkswagen.class, pp.getSpecialDeal());
Assertions.assertEquals("red", pp.getSpecialDeal().getColor()); // FAILS HERE
Assertions.assertEquals(true, pp.getSpecialDeal().getElectric());
});
}
private VolkswagenDealer createVolkswagenDealer(Session session) {
var vw = newVolkswagen();
var dealer = new VolkswagenDealer();
dealer.setSpecialDeal(vw);
session.persist(dealer);
return dealer;
}
private Volkswagen newVolkswagen() {
var vw = new Volkswagen();
vw.setColor("red");
vw.setElectric(true);
return vw;
}
It fails to persist and read the inherited Car#color property:
org.opentest4j.AssertionFailedError:
Expected :red
Actual :null
If I try querying the same color property:
@Test
void terminalEmbeddableReferenceQueryTest(SessionFactoryScope scope) throws Exception {
scope.inTransaction(session -> {
var pp = createVolkswagenDealer(session);
Assertions.assertNotNull(pp.getId());
session.flush();
var query = session.createQuery("SELECT DISTINCT vd.specialDeal.color FROM VolkswagenDealer vd");
var result = query.getSingleResult();
Assertions.assertEquals("red", result);
});
}
Again it fails, this time with:
java.lang.IllegalArgumentException: org.hibernate.query.sqm.UnknownPathException: Could not resolve attribute 'color' of 'org.hibernate.bugs.impl.embeddables.Volkswagen' [SELECT DISTINCT vd.specialDeal.color FROM VolkswagenDealer vd]
In fact if I look at the auto generated schema, you can see that the inherited color property is missing completely:
Hibernate:
create table VolkswagenDealer (
id bigint not null,
electric boolean,
primary key (id)
)
Is there any way to fix this, to achieve the model I want? I really want to preserve Java type compatibility and not introduce any more classes than I have to.
Thank you.
(Also posted at https://stackoverflow.com/q/79948638/1341535 with an expanded premise.)