java.lang.ClassCastException: class org.hibernate.query.sqm.tree.expression.SqmLiteral cannot be cast to class org.hibernate.metamodel.model.domain.internal.EntityDiscriminatorSqmPath (org.hibernate.query.sqm.tree.expression.SqmLiteral and org.hibernate.metamodel.model.domain.internal.EntityDiscriminatorSqmPath are in unnamed module of loader 'app')
Abstract base class: BaseShelter. This class has an embedded id (named AnimalNamePK) with a generic relation W extends Animal. Animal is an interface. Dog is an abstract class implementing this interface.
Below that we have BullDog and Collie.
Hi @ML-Marco, the error you’re encountering is caused by the generic bound of nimalNamePK (i.e. Animal) being an interface. When resolving the type of the animalNamePK.animal property, that results in a literal interface type, instead of a polymorphic entity’s discriminator.
The treat operator is only meant to be used on polymorphic entity-typed paths. You should rather be using the org.hibernate.query.criteria.HibernateCriteriaBuilder#cast to do a type-cast to Dog instead.
Sure, since Dog is not polymorphic just make animalNamePK.animal’s type Dog instead of a generic type parameter bound to an interface.
Note: HibernateCriteriaBuilder contains all Hibernate’s extensions to the JPA criteria APIs and, though it’s incubating, it offers many more useful functionalities you would not get otherwise.
Ok, if I understand this correctly animal cannot be an interface but must be some class that is an Entity. I tested it with with a class that is a @MappedSuperclass but that doesn’t work either. With animal being of type Dog it does work.
Unfortunately I can’t do this kind of change in the real application. So I tried your suggestion using cast of HibernateCriteriaBuilder. This lead to
org.hibernate.type.descriptor.java.spi.JdbcTypeRecommendationException: Could not determine recommended JdbcType for 'org.hibernate.bugs.Dog'
(criteriaBuilder.cast(animal, Dog.class))
Even if it worked, there is no way to do further joins or fetches on the dog object, no? That is because it returns a JpaExpression which doesn’t allow me to do any join or fetch.
Maybe I have a fundamental misunderstanding of the type hierarchy in Hibernate. While I can chain several joins, e.g. query.from(A.class).join("b").join("c") etc, as soon as I want to fetch something, I can’t continue, e.g. query.from(A.class).fetch("b").join("c") doesn’t work. Why is that?
Yes, the treat() operator must be used on polymorphic entity-typed path. As I suggested, the animal property’s generic type boundary should be an @Entity, which might even be an abstract-base class, and it should work.
We could probably handle this better. Please open a new improvement request in our tracker attaching your test case: we could probably handle mapped-superclasses better in this case and also at least produce a more significant error message for the non-managed type case.
JPA Criteria’s fetch method returns a FetchParent, that’s the main reason. You can try re-using the fetched path, e.g. a.fetch("b"); a.get("b").join("c"), but note that re-using join fetches might be implementation-dependant. Otherwise, you would have to use Hibernate’s SQM model APIs (see e.g. AbstractSqmFrom#fetch) that produce join-typed objects for fetch when suitable.