Thanks for the quick reply!
Before I go build a patched Hibernate — is replacing the translator via hibernate.query.hql.translator (QuerySettings.SEMANTIC_QUERY_PRODUCER) an equivalent experiment? HqlTranslator is a single-method interface, so I could ship a copy of StandardHqlTranslator#parseHql that skips the SLL pass and goes straight to PredictionMode.LL with the DefaultErrorStrategy. That would let me run it in production, where we reliably see the error about once per pod start, instead of only in a test environment where I have never reproduced it.
If that is not equivalent (e.g. the custom translator is not used on every path, or something else about the setup differs), I will build the patched jar instead — just let me know which you prefer.
Everything you asked for is below.
Full stack trace
BadJpqlGrammarException — AdCta case
org.springframework.data.jpa.repository.query.BadJpqlGrammarException: org.hibernate.query.SemanticException: Could not interpret path expression ‘S.chipId’; Bad SELECT a FROM AdCta a WHERE a.chipId IN :chipIds ORDER BY a.seq asc grammar [JPQL]
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.createQuery(PartTreeJpaQuery.java:242)
Suppressed: The stacktrace has been enhanced by Reactor, refer to additional information below:
Error has been observed at the following site(s):
*__checkpoint ⇢ Handler com.example.app.SomeResource#someHandler(…) [DispatcherHandler]
Original Stack Trace:
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.createQuery(PartTreeJpaQuery.java:242)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.doCreateQuery(PartTreeJpaQuery.java:125)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.createQuery(AbstractJpaQuery.java:266)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:141)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:100)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:166)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:156)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:169)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:167)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:146)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:69)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:133)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:371)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:130)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:135)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.util.NullnessMethodInvocationValidator.invoke(NullnessMethodInvocationValidator.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:222)
at jdk.proxy3/jdk.proxy3.$Proxy246.findAllByChipIdInOrderBySeqAsc(Unknown Source)
at com.example.app.ChipProvider$getChips$2.invokeSuspend(ChipProvider.kt:49)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:124)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:89)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:586)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:820)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:717)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:704)
Caused by: java.lang.IllegalArgumentException: org.hibernate.query.SemanticException: Could not interpret path expression ‘S.chipId’
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:134)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:173)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:179)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:1102)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:158)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:1011)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:158)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:154)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:565)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:360)
at jdk.proxy3/jdk.proxy3.$Proxy215.createQuery(Unknown Source)
… (Spring proxy frames omitted) …
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.createQuery(PartTreeJpaQuery.java:240)
… 50 common frames omitted
Caused by: org.hibernate.query.SemanticException: Could not interpret path expression ‘S.chipId’
at org.hibernate.query.hql.internal.BasicDotIdentifierConsumer$BaseLocalSequencePart.resolveTerminal(BasicDotIdentifierConsumer.java:180)
at org.hibernate.query.hql.internal.BasicDotIdentifierConsumer$BaseLocalSequencePart.resolvePathPart(BasicDotIdentifierConsumer.java:153)
at org.hibernate.query.hql.internal.BasicDotIdentifierConsumer.consumeIdentifier(BasicDotIdentifierConsumer.java:90)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSimplePath(SemanticQueryBuilder.java:5790)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitGeneralPathFragment(SemanticQueryBuilder.java:5645)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitGeneralPathExpression(SemanticQueryBuilder.java:1815)
at org.hibernate.grammars.hql.HqlParser$GeneralPathExpressionContext.accept(HqlParser.java:7847)
at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visitChildren(AbstractParseTreeVisitor.java:46)
at org.hibernate.grammars.hql.HqlParserBaseVisitor.visitBarePrimaryExpression(HqlParserBaseVisitor.java:761)
at org.hibernate.grammars.hql.HqlParser$BarePrimaryExpressionContext.accept(HqlParser.java:7296)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitInPredicate(SemanticQueryBuilder.java:3267)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitInPredicate(SemanticQueryBuilder.java:247)
at org.hibernate.grammars.hql.HqlParser$InPredicateContext.accept(HqlParser.java:6392)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitWhereClause(SemanticQueryBuilder.java:2330)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitWhereClause(SemanticQueryBuilder.java:247)
at org.hibernate.grammars.hql.HqlParser$WhereClauseContext.accept(HqlParser.java:6146)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitQuery(SemanticQueryBuilder.java:1163)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitQuerySpecExpression(SemanticQueryBuilder.java:956)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitQuerySpecExpression(SemanticQueryBuilder.java:247)
at org.hibernate.grammars.hql.HqlParser$QuerySpecExpressionContext.accept(HqlParser.java:2113)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitQueryExpression(SemanticQueryBuilder.java:985)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitQueryExpression(SemanticQueryBuilder.java:247)
at org.hibernate.grammars.hql.HqlParser$QueryExpressionContext.accept(HqlParser.java:2003)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSelectStatement(SemanticQueryBuilder.java:472)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitStatement(SemanticQueryBuilder.java:431)
at org.hibernate.query.hql.internal.SemanticQueryBuilder.buildSemanticModel(SemanticQueryBuilder.java:292)
at org.hibernate.query.hql.internal.StandardHqlTranslator.translate(StandardHqlTranslator.java:61)
at org.hibernate.query.internal.QueryInterpretationCacheStandardImpl.createHqlInterpretation(QueryInterpretationCacheStandardImpl.java:165)
at org.hibernate.query.internal.QueryInterpretationCacheStandardImpl.resolveHqlInterpretation(QueryInterpretationCacheStandardImpl.java:147)
at org.hibernate.query.spi.QueryEngine.interpretHql(QueryEngine.java:61)
at org.hibernate.internal.AbstractSharedSessionContract.interpretHql(AbstractSharedSessionContract.java:1043)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:1094)
… 50 common frames omitted
Note the failure comes from the SLL/LL path in StandardHqlTranslator.translate → SemanticQueryBuilder.buildSemanticModel, reached through QueryInterpretationCacheStandardImpl.createHqlInterpretation (i.e. a cache miss).
Entities
Kotlin, but plain JPA annotations — no Hibernate-specific mappings, no associations between these two entities (AdCta.chipId is a plain Long, not a @ManyToOne).
@MappedSuperclass
@EntityListeners(AuditingEntityListener::class)
abstract class BaseEntity {
@CreatedDate
@Column(name = "created_at", nullable = false, updatable = false)
lateinit var createdAt: LocalDateTime
@LastModifiedDate
@Column(name = "modified_at")
lateinit var modifiedAt: LocalDateTime
}
@EntityListeners(AuditingEntityListener::class)
@Entity
@Table(name = "ad_cta")
class AdCta(
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long? = null,
@Column(name = "chip_id", nullable = false)
val chipId: Long,
@Column(name = "seq", nullable = false)
var seq: Int,
@Column(name = "label", length = 50, nullable = false)
@Column(name = "label", length = 50, nullable = false)
var label: String,
@Enumerated(EnumType.STRING)
@Column(name = "link_type", length = 16, nullable = false)
var linkType: AdCtaLinkType,
@Column(name = "link_value", length = 1024, nullable = false)
var linkValue: String,
) : BaseEntity()
@EntityListeners(AuditingEntityListener::class)
@Entity
@Table(name = "ad_chip")
class AdChip(
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long? = null,
@Column(name = "group_id", nullable = false)
val groupId: Long,
@Column(name = "display_order", nullable = false)
var displayOrder: Int,
@Column(name = "active", nullable = false, columnDefinition = "TINYINT(1)")
var active: Boolean = true,
@Column(name = "list_label", length = 8, nullable = false)
var listLabel: String,
@Enumerated(EnumType.STRING)
@Column(name = "material_type", length = 16, nullable = false)
var materialType: AdMaterialType,
// ... remaining columns are plain String?/Int? fields
) : BaseEntity()
Repositories (both are plain derived queries)
interface AdCtaRepository : JpaRepository<AdCta, Long> {
fun findAllByChipIdOrderBySeqAsc(chipId: Long): List
fun findAllByChipIdInOrderBySeqAsc(chipIds: List): List // ← fails
fun deleteAllByChipId(chipId: Long)
}
interface AdChipRepository : JpaRepository<AdChip, Long> {
fun findAllByGroupIdOrderByDisplayOrderAsc(groupId: Long): List
fun findAllByGroupIdAndActiveIsTrueOrderByDisplayOrderAsc(groupId: Long): List // ← also fails
// ...
}
Both are called from the same method, one right after the other:
val chips = chipRepository.findAllByGroupIdAndActiveIsTrueOrderByDisplayOrderAsc(group.id!!)
if (chips.isEmpty()) return@withContext emptyList()
val ctasByChipId = ctaRepository
.findAllByChipIdInOrderBySeqAsc(chips.map { it.id!! })
.groupBy { it.chipId }
This runs inside withContext(Dispatchers.IO), so both queries execute on a shared JDBC thread pool — several requests can be parsing HQL concurrently right after startup.
Relevant Hibernate settings
hibernate.hbm2ddl.auto: validate
hibernate.jdbc.time_zone: Asia/Seoul
hibernate.default_batch_fetch_size: 100
hibernate.cache.use_second_level_cache: false
hibernate.cache.use_query_cache: false
hibernate.order_inserts: true
hibernate.order_updates: true
hibernate.jdbc.batch_size: 50
hibernate.jdbc.batch_versioned_data: true
No custom HqlTranslator, no custom dialect beyond the MySQL one, query plan cache left at defaults.