hibernate/hibernate-orm · error · StrictJpaComplianceViolation
Strict JPA query language compliance was violated: use of im
Error message
Strict JPA query language compliance was violated: use of implicit treat
What it means
When strict JPA query compliance is enabled (hibernate.query.jpa_compliance_strict / legacy hibernate.query.jpa.compliance), Hibernate rejects queries that rely on implicit treat: referencing a subclass attribute on a supertype alias (p.subclassField) without an explicit TREAT. Normally Hibernate silently applies an implicit downcast; strict mode throws StrictJpaComplianceViolation of type IMPLICIT_TREAT from BasicValuedPathInterpretation.modelPartError, because the attribute is not found on the table group for the static type but would be found via treat handling.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/BasicValuedPathInterpretation.java:109
final var tableReference =
tableGroup.resolveTableReference( navigablePath, mapping, mapping.getContainingTableExpression() );
final var expression =
sqlAstCreationState.getSqlExpressionResolver()
.resolveSqlExpression( tableReference, mapping );
return new BasicValuedPathInterpretation<>( columnReference( expression ), navigablePath, mapping, tableGroup );
}
private static <T> void modelPartError(
SqmBasicValuedSimplePath<T> sqmPath,
boolean jpaQueryComplianceEnabled,
TableGroup tableGroup) {
if ( jpaQueryComplianceEnabled ) {
// to get the better error, see if we got nothing because of treat handling
final var subPart =
tableGroup.getModelPart()
.findSubPart( sqmPath.getReferencedPathSource().getPathName(), null );
if ( subPart != null ) {
throw new StrictJpaComplianceViolation( StrictJpaComplianceViolation.Type.IMPLICIT_TREAT );
}
}
throw new UnknownPathException( "Path '" + sqmPath.getNavigablePath() + "' did not reference a known model part" );
}
private static ColumnReference columnReference(Expression expression) {
if ( expression instanceof ColumnReference reference ) {
return reference;
}
else if ( expression instanceof SqlSelectionExpression selection ) {
final var selectedExpression = selection.getSelection().getExpression();
assert selectedExpression instanceof ColumnReference;
return (ColumnReference) selectedExpression;
}
else {
throw new UnsupportedOperationException( "Unsupported basic-valued path expression : " + expression );
}View on GitHub (pinned to fad1729dce)
Solutions
- Make the treat explicit: 'from Person p where treat(p as Employee).salary > 100'
- Query the subtype entity directly: 'from Employee e where e.salary > 100'
- If the implicit behavior is intended, disable strict compliance: set hibernate.query.jpa_compliance_strict=false (and hibernate.query.jpa.compliance=false on older versions) in persistence.xml or SessionFactory settings
- Move shared fields up to the superclass so no downcast is needed
Example fix
-- before (strict compliance on) from Person p where p.salary > 100 -- after from Person p where treat(p as Employee).salary > 100 <!-- or relax the setting --> <property name="hibernate.query.jpa_compliance_strict" value="false"/>
Defensive patterns
Strategy: validation
Validate before calling
Map<String, Object> props = new HashMap<>();
boolean strict = sessionFactory.getOptions().isStrictJpaQueryCompliance();
if (strict) { /* ensure all subclass references use explicit treat before running */ } Type guard
static boolean referencesSubclassFieldOnBase(String hql, Set<String> subclassFields) {
return subclassFields.stream().anyMatch(f -> hql.matches("(?i).*\\bp\\." + f + ".*"));
} Try / catch
catch (StrictJpaComplianceViolation e) { /* switch query to explicit treat(p as Sub) or disable strict compliance globally */ } Prevention
- Decide once whether strict JPA compliance is required; document it
- Write queries with explicit TREAT from the start so they pass both modes
- Test the full query corpus under strict mode when enabling it
When it happens
Trigger: Setting AvailableSettings.JPA_QUERY_COMPLIANCE (or strict compliance) to true and running HQL like 'from Person p where p.salary > 100' where salary belongs only to Employee; JPQL ported between providers where implicit downcasting was never legal; criteria queries building root.get("salary") on a base-class root under strict mode.
Common situations: Enabling JPA compliance for certification or portability (moving an app to another JPA provider); upgrading Hibernate versions where the compliance flag defaults or interpretation changed; enabling strict mode to silence other legacy HQL behavior and suddenly breaking polymorphic queries that relied on implicit treats.
Related errors
- NON_ENTITY_NAME
- UNMAPPED_POLYMORPHISM
- Implicitly-polymorphic domain path in subquery '${name}'
- FROM_SUBQUERY
- FROM_FUNCTION
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/c7a2232a22ca569e.
Report an issue: GitHub.