{"record":{"id":"c7a2232a22ca569e","repo":"hibernate/hibernate-orm","slug":"strict-jpa-query-language-compliance-was-violated-c7a223","errorCode":null,"errorMessage":"Strict JPA query language compliance was violated: use of implicit treat","messagePattern":"Strict JPA query language compliance was violated: use of implicit treat","errorType":"exception","errorClass":"StrictJpaComplianceViolation","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/BasicValuedPathInterpretation.java","lineNumber":109,"sourceCode":"\t\tfinal var tableReference =\n\t\t\t\ttableGroup.resolveTableReference( navigablePath, mapping, mapping.getContainingTableExpression() );\n\t\tfinal var expression =\n\t\t\t\tsqlAstCreationState.getSqlExpressionResolver()\n\t\t\t\t\t\t.resolveSqlExpression( tableReference, mapping );\n\t\treturn new BasicValuedPathInterpretation<>( columnReference( expression ), navigablePath, mapping, tableGroup );\n\t}\n\n\tprivate static <T> void modelPartError(\n\t\t\tSqmBasicValuedSimplePath<T> sqmPath,\n\t\t\tboolean jpaQueryComplianceEnabled,\n\t\t\tTableGroup tableGroup) {\n\t\tif ( jpaQueryComplianceEnabled ) {\n\t\t\t// to get the better error, see if we got nothing because of treat handling\n\t\t\tfinal var subPart =\n\t\t\t\t\ttableGroup.getModelPart()\n\t\t\t\t\t\t\t.findSubPart( sqmPath.getReferencedPathSource().getPathName(), null );\n\t\t\tif ( subPart != null ) {\n\t\t\t\tthrow new StrictJpaComplianceViolation( StrictJpaComplianceViolation.Type.IMPLICIT_TREAT );\n\t\t\t}\n\t\t}\n\n\t\tthrow new UnknownPathException( \"Path '\" + sqmPath.getNavigablePath() + \"' did not reference a known model part\" );\n\t}\n\n\tprivate static ColumnReference columnReference(Expression expression) {\n\t\tif ( expression instanceof ColumnReference reference ) {\n\t\t\treturn reference;\n\t\t}\n\t\telse if ( expression instanceof SqlSelectionExpression selection ) {\n\t\t\tfinal var selectedExpression = selection.getSelection().getExpression();\n\t\t\tassert selectedExpression instanceof ColumnReference;\n\t\t\treturn (ColumnReference) selectedExpression;\n\t\t}\n\t\telse {\n\t\t\tthrow new UnsupportedOperationException( \"Unsupported basic-valued path expression : \" + expression );\n\t\t}","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/BasicValuedPathInterpretation.java#L91-L127","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"-- before (strict compliance on)\nfrom Person p where p.salary > 100\n-- after\nfrom Person p where treat(p as Employee).salary > 100\n\n<!-- or relax the setting -->\n<property name=\"hibernate.query.jpa_compliance_strict\" value=\"false\"/>","handlingStrategy":"validation","validationCode":"Map<String, Object> props = new HashMap<>();\nboolean strict = sessionFactory.getOptions().isStrictJpaQueryCompliance();\nif (strict) { /* ensure all subclass references use explicit treat before running */ }","typeGuard":"static boolean referencesSubclassFieldOnBase(String hql, Set<String> subclassFields) {\n    return subclassFields.stream().anyMatch(f -> hql.matches(\"(?i).*\\\\bp\\\\.\" + f + \".*\"));\n}","tryCatchPattern":"catch (StrictJpaComplianceViolation e) { /* switch query to explicit treat(p as Sub) or disable strict compliance globally */ }","preventionTips":["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"],"tags":["hibernate","jpa-compliance","implicit-treat","hql","polymorphism","configuration"],"backgroundTag":"strict-jpa-compliance-violation","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}