Given the following domain model, I want to load all Answer
s including their Value
s and their respective sub-children and put it in an AnswerDTO<
I don't know what Spring-Data is doing there, but to do that, you usually have to use the TREAT
operator to be able to access the sub-association but the implementation for that Operator is quite buggy.
Hibernate supports implicit subtype property access which is what you would need here, but apparently Spring-Data can't handle this properly. I can recommend that you take a look at Blaze-Persistence Entity-Views, a library that works on top of JPA which allows you map arbitrary structures against your entity model. You can map your DTO model in a type safe way, also the inheritance structure. Entity views for your use case could look like this
@EntityView(Answer.class)
interface AnswerDTO {
@IdMapping
Long getId();
ValueDTO getValue();
}
@EntityView(Value.class)
@EntityViewInheritance
interface ValueDTO {
@IdMapping
Long getId();
}
@EntityView(TextValue.class)
interface TextValueDTO extends ValueDTO {
String getText();
}
@EntityView(RatingValue.class)
interface RatingValueDTO extends ValueDTO {
int getRating();
}
@EntityView(MCValue.class)
interface TextValueDTO extends ValueDTO {
@Mapping("selected.id")
Set getOption();
}
With the spring data integration provided by Blaze-Persistence you can define a repository like this and directly use the result
@Transactional(readOnly = true)
interface AnswerRepository extends Repository {
List findAll();
}
It will generate a HQL query that selects just what you mapped in the AnswerDTO
which is something like the following.
SELECT
a.id,
v.id,
TYPE(v),
CASE WHEN TYPE(v) = TextValue THEN v.text END,
CASE WHEN TYPE(v) = RatingValue THEN v.rating END,
CASE WHEN TYPE(v) = MCValue THEN s.id END
FROM Answer a
LEFT JOIN a.value v
LEFT JOIN v.selected s