quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.57k stars 2.63k forks source link

Quarkus Hibernate 6.x throws SemanticException: Could not interpret path expression 'property_state' but column exists #42921

Closed dhoffer closed 5 days ago

dhoffer commented 2 weeks ago

Describe the bug

After upgrading to Quarkus 3.14.1 (from 2.16.12.Final) I get a Hibernate error where it can't interpet a column name. I'm using PostgreSQL & Panache.

2024-08-30 20:43:42,811 qsd1 /nix/store/gm0dgz25420fimf0knw4srkvzhpqrnai-openjdk-17.0.7+7/lib/openjdk/bin/java[116398] ERROR [io.qua.run.Application] (main) Failed to start application: java.lang.RuntimeException: Failed to start quarkus at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source) at io.quarkus.runtime.Application.start(Application.java:101) at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:119) at io.quarkus.runtime.Quarkus.run(Quarkus.java:71) at io.quarkus.runtime.Quarkus.run(Quarkus.java:44) at com.qsd.jmb.preapprovalapp.app.Main.main(Main.java:20) Caused by: org.hibernate.query.SemanticException: Could not interpret path expression 'property_state' at org.hibernate.query.hql.internal.BasicDotIdentifierConsumer$BaseLocalSequencePart.resolvePathPart(BasicDotIdentifierConsumer.java:240) at org.hibernate.query.hql.internal.BasicDotIdentifierConsumer.consumeIdentifier(BasicDotIdentifierConsumer.java:92) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSimplePath(SemanticQueryBuilder.java:5454) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitGeneralPathFragment(SemanticQueryBuilder.java:5297) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitGeneralPathExpression(SemanticQueryBuilder.java:1891) at org.hibernate.grammars.hql.HqlParser$GeneralPathExpressionContext.accept(HqlParser.java:8268) at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visitChildren(AbstractParseTreeVisitor.java:46) at org.hibernate.grammars.hql.HqlParserBaseVisitor.visitBarePrimaryExpression(HqlParserBaseVisitor.java:812) at org.hibernate.grammars.hql.HqlParser$BarePrimaryExpressionContext.accept(HqlParser.java:7726) at org.hibernate.query.hql.internal.SemanticQueryBuilder.createComparisonPredicate(SemanticQueryBuilder.java:2548) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitComparisonPredicate(SemanticQueryBuilder.java:2509) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitComparisonPredicate(SemanticQueryBuilder.java:277) at org.hibernate.grammars.hql.HqlParser$ComparisonPredicateContext.accept(HqlParser.java:6611) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitAndPredicate(SemanticQueryBuilder.java:2378) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitAndPredicate(SemanticQueryBuilder.java:277) at org.hibernate.grammars.hql.HqlParser$AndPredicateContext.accept(HqlParser.java:6461) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitWhereClause(SemanticQueryBuilder.java:2361) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitWhereClause(SemanticQueryBuilder.java:277) at org.hibernate.grammars.hql.HqlParser$WhereClauseContext.accept(HqlParser.java:6302) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitQuery(SemanticQueryBuilder.java:1259) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitQuerySpecExpression(SemanticQueryBuilder.java:1040) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitQuerySpecExpression(SemanticQueryBuilder.java:277) at org.hibernate.grammars.hql.HqlParser$QuerySpecExpressionContext.accept(HqlParser.java:2134) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSimpleQueryGroup(SemanticQueryBuilder.java:1025) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSimpleQueryGroup(SemanticQueryBuilder.java:277) at org.hibernate.grammars.hql.HqlParser$SimpleQueryGroupContext.accept(HqlParser.java:2005) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSelectStatement(SemanticQueryBuilder.java:492) at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitStatement(SemanticQueryBuilder.java:451) at org.hibernate.query.hql.internal.SemanticQueryBuilder.buildSemanticModel(SemanticQueryBuilder.java:324) at org.hibernate.query.hql.internal.StandardHqlTranslator.translate(StandardHqlTranslator.java:71) at org.hibernate.query.internal.QueryInterpretationCacheStandardImpl.createHqlInterpretation(QueryInterpretationCacheStandardImpl.java:145) at org.hibernate.query.internal.QueryInterpretationCacheStandardImpl.resolveHqlInterpretation(QueryInterpretationCacheStandardImpl.java:132) at org.hibernate.query.spi.QueryEngine.interpretHql(QueryEngine.java:54) at org.hibernate.internal.AbstractSharedSessionContract.interpretHql(AbstractSharedSessionContract.java:831) at org.hibernate.internal.AbstractSharedSessionContract.interpretAndCreateSelectionQuery(AbstractSharedSessionContract.java:809) at org.hibernate.internal.AbstractSharedSessionContract.createSelectionQuery(AbstractSharedSessionContract.java:856) at io.quarkus.hibernate.orm.runtime.session.TransactionScopedSession.createSelectionQuery(TransactionScopedSession.java:1277) at org.hibernate.engine.spi.SessionLazyDelegator.createSelectionQuery(SessionLazyDelegator.java:749) at org.hibernate.Session_ilTHnt5-Rtrc-lcyZ-6tBgAWKh4_Synthetic_ClientProxy.createSelectionQuery(Unknown Source) at io.quarkus.hibernate.orm.panache.common.runtime.CommonPanacheQueryImpl.createBaseQuery(CommonPanacheQueryImpl.java:387) at io.quarkus.hibernate.orm.panache.common.runtime.CommonPanacheQueryImpl.createQuery(CommonPanacheQueryImpl.java:348) at io.quarkus.hibernate.orm.panache.common.runtime.CommonPanacheQueryImpl.list(CommonPanacheQueryImpl.java:301) at io.quarkus.hibernate.orm.panache.runtime.PanacheQueryImpl.list(PanacheQueryImpl.java:150) at io.quarkus.hibernate.orm.panache.runtime.JpaOperations.list(JpaOperations.java:24) at io.quarkus.hibernate.orm.panache.runtime.JpaOperations.list(JpaOperations.java:10) at io.quarkus.hibernate.orm.panache.common.runtime.AbstractJpaOperations.list(AbstractJpaOperations.java:249) at com.qsd.jmb.db.preapprovalapp.repository.TitleInsuranceRepository.list(TitleInsuranceRepository.java) at com.qsd.jmb.db.preapprovalapp.repository.TitleInsuranceRepository_Subclass.list$$superforward(Unknown Source) at com.qsd.jmb.db.preapprovalapp.repository.TitleInsuranceRepository_Subclass$$function$$22.apply(Unknown Source) at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:73) at io.quarkus.arc.impl.AroundInvokeInvocationContext.proceed(AroundInvokeInvocationContext.java:62) at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.invokeInCallerTx(TransactionalInterceptorBase.java:335) at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired.doIntercept(TransactionalInterceptorRequired.java:40) at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorBase.intercept(TransactionalInterceptorBase.java:61) at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired.intercept(TransactionalInterceptorRequired.java:32) at io.quarkus.narayana.jta.runtime.interceptor.TransactionalInterceptorRequired_Bean.intercept(Unknown Source) at io.quarkus.arc.impl.InterceptorInvocation.invoke(InterceptorInvocation.java:42) at io.quarkus.arc.impl.AroundInvokeInvocationContext.perform(AroundInvokeInvocationContext.java:30) at io.quarkus.arc.impl.InvocationContexts.performAroundInvoke(InvocationContexts.java:27)

Here is the Enity column:

@Column(name="property_state", nullable=false, length=2) public String getPropertyState() { return this.propertyState; }

public void setPropertyState(String propertyState) {
    this.propertyState = propertyState;
}

The Panache query is:

return list(String.format("%s = ?1 and %s = ?2", PROPERTY_STATE, TRANSACTION_TYPE), state, transaction);

Expected behavior

It should be able to find the column just like it used to in version 2.16.12.Final.

Actual behavior

It throws a org.hibernate.query.SemanticException: Could not interpret path expression 'property_state'

How to Reproduce?

No response

Output of uname -a or ver

No response

Output of java -version

java 17.0.9 2023-10-17 LTS

Quarkus version or git rev

3.14.1

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.9.6 (bc0240f3c744dd6b6ec2920b3cd08dcc295161ae)

Additional information

No response

quarkus-bot[bot] commented 2 weeks ago

/cc @gsmet (hibernate-orm), @yrodiere (hibernate-orm)

dhoffer commented 2 weeks ago

I went and tried all the latest service pack versions from 3.14.1 to 3.9.5 and they all have this bug. I can't go back prior to 3.9.5 w/o also reverting to the prior quarkus-rest & quarkus-rest-jackson artifact names.

Also, the DB table & column name that it fails on appears to be somewhat random, they don't all fail but eventually one does and the app crashes.

So is this a known issue that Quarkus 3.x with Hibernate 6.x with Panache and Postgres is broken? Is there any workaround? This is a huge blocker.

gsmet commented 2 weeks ago

Did you try propertyState? I have a vague recollection that you need to use the property name and not the column name now. I think it was documented in one of the migration guides.

yrodiere commented 1 week ago

Did you try propertyState? I have a vague recollection that you need to use the property name and not the column name now. I think it was documented in one of the migration guides.

+1. property_state is a column name, used in SQL, but Panache works with HQL, which expects JPA attribute names, so in this case propertyState.

If property_state was accepted before, it was most likely a bug, and indeed I remember something about that being fixed in an earlier version, to avoid ambiguity in some models/queries.

If someone finds in which version this was fixed, we should definitely mention this change prominently in the migration guide. I think the behavior was changed in Quarkus 3.0 as part of the HQL parsing overhaul in Hibernate ORM 6.0/6.1/6.2, but we'd have to test this -- I can't find the relevant Jira issue.

But first, please confirm whether propertyState works correctly?

dhoffer commented 1 week ago

No, I have never tried the JPA name, only the DB column name as that was what was required in Quarkus 2.x and I didn't know it changed. Yeah this change should be noted in the online docs.

-David

On Tue, Sep 3, 2024 at 1:17 AM Yoann Rodière @.***> wrote:

Did you try propertyState? I have a vague recollection that you need to use the property name and not the column name now. I think it was documented in one of the migration guides.

+1. property_state is a column name, used in SQL, but Panache works with HQL, which expects JPA attribute names, so in this case propertyState.

If property_state was accepted before, it was most likely a bug, and indeed I remember something about that being fixed in an earlier version, to avoid ambiguity in some models/queries.

If someone finds in which version this was fixed, we should definitely mention this change prominently in the migration guide. I think the behavior was changed in Quarkus 3.0 as part of the HQL parsing overhaul in Hibernate ORM 6.0/6.1/6.2, but we'd have to test this -- I can't find the relevant Jira issue.

But first, please confirm whether propertyState works correctly?

— Reply to this email directly, view it on GitHub https://github.com/quarkusio/quarkus/issues/42921#issuecomment-2325773403, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAL7BLZ7OC7XC7MXNEU6R5LZUVO7RAVCNFSM6AAAAABNNEY4PKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGMRVG43TGNBQGM . You are receiving this because you authored the thread.Message ID: @.***>

yrodiere commented 1 week ago

No, I have never tried the JPA name, only the DB column name as that was what was required in Quarkus 2.x and I didn't know it changed

To be clear I'd expect Quarkus 2.x didn't require the column name, but just accepted it (incorrectly). I'd expect the JPA attribute name to work in Quarkus 2.x.

dhoffer commented 1 week ago

Regarding Quarkus 2.x you might be right, column names always worked so I always used them. So if 3.x JPA names are required, this works for joined table names too? e.g. Quarkus will know that a JPA field name of table2 (In the table1 entity) which is joined by column name table2_id (varchar) will just work?

On Tue, Sep 3, 2024 at 6:49 AM Yoann Rodière @.***> wrote:

No, I have never tried the JPA name, only the DB column name as that was what was required in Quarkus 2.x and I didn't know it changed

To be clear I'd expect Quarkus 2.x didn't require the column name, but just accepted it (incorrectly). I'd expect the JPA attribute name to work in Quarkus 2.x.

— Reply to this email directly, view it on GitHub https://github.com/quarkusio/quarkus/issues/42921#issuecomment-2326441678, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAL7BLYRRRDKMRFWZXBG4BTZUWV6HAVCNFSM6AAAAABNNEY4PKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGMRWGQ2DCNRXHA . You are receiving this because you authored the thread.Message ID: @.***>

yrodiere commented 1 week ago

So if 3.x JPA names are required, this works for joined table names too?

When you use Panache, you use HQL, Hibernate Query Language, which is an extension of JPQL, JPA Query Language. Both of these query languages are working at the entity level. So there is no table or column, everything you mention there should be entity names and attribute (~ Java field) names.

e.g. Quarkus will know that a JPA field name of table2 (In the table1 entity) which is joined by column name table2_id (varchar) will just work?

I'm having trouble picturing what you mean (a precise query would help), but in general yes, joins in JPQL work. The syntax is a bit different though, as -- as always -- you give entity/attribute names, not column names. See here for more information: https://docs.jboss.org/hibernate/orm/6.6/querylanguage/html_single/Hibernate_Query_Language.html#join

dhoffer commented 1 week ago

I have confirmed that Hibernate 6.x does work propertly if I use the JPA names and not the column names. I think this should be stated in the Panache documentation as its a big change that is not documented anywhere as far as I know.

yrodiere commented 6 days ago

Thank you for confirming.

To be fair, nowhere was it documented that you could use column names instead of attribute names -- IIRC, it was considered a bug.

But yes, it should appear in the migration guide. Do you happen to know in what version of Quarkus exactly this change occurred?

dhoffer commented 6 days ago

No not sure of the version but I found it during upgrading from 2.16.12 to a fairly recent 3.x version. Ideally I'd like it to support both but just JPA names works.

yrodiere commented 5 days ago

I just ran a few tests, and it's been this way since Hibernate ORM 6.0. Only 5.x and below accept column names in HQL queries -- and even then, only in some cases: in a "select" clause you'd get an error about "unknown type" since Hibernate ORM 5.x wouldn't completely understand what the column name refers to.

I'll update the migration guides, thanks for reporting.

I'll close this since it's not a bug, but feel free to comment, or open another issue if you have other problems.