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

  1. Make the treat explicit: 'from Person p where treat(p as Employee).salary > 100'
  2. Query the subtype entity directly: 'from Employee e where e.salary > 100'
  3. 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
  4. 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

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


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/c7a2232a22ca569e. Report an issue: GitHub.