Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HHH-15802 ubQuery with "in" results in java.lang.ClassCastException: class org.hibernate.metamodel.mapping.internal.BasicEntityIdentifierMappingImpl cannot be cast to class org.hibernate.metamodel.mapping.EntityValuedModelPart #5800

Closed
wants to merge 2 commits into from

Conversation

dreab8
Copy link
Member

@dreab8 dreab8 commented Dec 19, 2022

… class org.hibernate.metamodel.mapping.internal.BasicEntityIdentifierMappingImpl cannot be cast to class org.hibernate.metamodel.mapping.EntityValuedModelPart
@beikov
Copy link
Contributor

beikov commented Dec 19, 2022

I don't think that we should support this. IMO it was a bug that this worked before.

@csware
Copy link
Contributor

csware commented Dec 20, 2022

Why shouldn't this be supported? If not, then you should adjust the API (data types) that this is not possible anymore (so you get an compile time error).

In with subquery is perfect valid SQL. I know no other ways to build such queries with the criteria API (without using HQL etc).

@beikov
Copy link
Contributor

beikov commented Dec 20, 2022

Try using the static metamodel and then you will see a compile error:

criteria.where(root.get(Participation_.id).in(subQuery));

@csware
Copy link
Contributor

csware commented Dec 20, 2022

Try using the static metamodel and then you will see a compile error:

criteria.where(root.get(Participation_.id).in(subQuery));

That is exactly what I reported in the original issue (https://hibernate.atlassian.net/jira/software/c/projects/HHH/issues/HHH-15802) and that works with 5.6.14 AND 6.1.6 (but I get a runtime error >=6.1.1). Look at https://github.com/csware/si if you want to see yourself in a full project.

@beikov
Copy link
Contributor

beikov commented Dec 20, 2022

Hmm, the jakarta.persistence.criteria.Path#in() methods don't specify the type variable, which seems fishy to me. It IMO just doesn't make sense to compare an expression of type Integer with an expression of type Participation. The easy fix for you is to just remove the .get(Participation_.id) part. We have to discuss this with the team, but -1 from me for continuing to support this IMO ill-typed way of doing things. These sort of special cases complicate things in the translation code all over the place for IMO no benefit. The proper way is even shorter for users to write.

@csware
Copy link
Contributor

csware commented Dec 20, 2022

Removing the .get part works for me and would be a solution (added that workaround to the issue).

@beikov
Copy link
Contributor

beikov commented Dec 20, 2022

Let's please not call it a workaround, as it's the proper way to do the comparison you are aiming for. You surely understand that comparing apples with oranges simply isn't the right thing to do. Most statically typed programming languages will not allow to comparing objects with values and I think nobody should rely on something like that.

@csware
Copy link
Contributor

csware commented Dec 20, 2022

There are still other places in current Hibernate (>= 6.1.1) where this still works:

CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Lecture> criteria = builder.createQuery(Lecture.class);
Root<Lecture> root = criteria.from(Lecture.class);
criteria.select(root);
criteria.orderBy(builder.asc(root.get(Lecture_.name)), builder.desc(root.get(Lecture_.semester)));

Subquery<Lecture> subQuery = criteria.subquery(Lecture.class);
Root<Participation> lecturesTakingPartIn = subQuery.from(Participation.class);
subQuery.select(lecturesTakingPartIn.get(Participation_.lecture));
subQuery.where(builder.equal(lecturesTakingPartIn.get(Participation_.user), user));

criteria.where(builder.not(root.get(Lecture_.id).in(subQuery)));

return session.createQuery(criteria).list();

The only difference seems to be that the subQuery.select is "multivalued". It is at least inconsistent ATM.

@gavinking
Copy link
Member

Hmm, the jakarta.persistence.criteria.Path#in() methods don't specify the type variable, which seems fishy to me. It IMO just doesn't make sense to compare an expression of type Integer with an expression of type Participation. The easy fix for you is to just remove the .get(Participation_.id) part. We have to discuss this with the team, but -1 from me for continuing to support this IMO ill-typed way of doing things. These sort of special cases complicate things in the translation code all over the place for IMO no benefit. The proper way is even shorter for users to write.

I have no strong opinion on this, but it's definitely wrong that the user experiences a ClassCastException instead of a meaningful error, so something needs to be fixed here.

@beikov
Copy link
Contributor

beikov commented Mar 2, 2023

Closing this in favor of #6189 since we will rather make sure we drop support for this unsafe error prone comparison of entity valued paths against basic valued paths/literals

@beikov beikov closed this Mar 2, 2023
@gavinking
Copy link
Member

drop support for this unsafe error prone comparison of entity valued paths against basic valued paths/literals

is it documented in the migration guide?

@beikov
Copy link
Contributor

beikov commented Mar 2, 2023

@dreab8 will document it as part of #6189

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants