{"record":{"id":"1256a2e8c47e8fba","repo":"hibernate/hibernate-orm","slug":"join-type-has-no-jpa-join-type-mapping","errorCode":null,"errorMessage":"Join type has no JPA join type mapping: {}","messagePattern":"Join type has no JPA join type mapping: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/SqmJoinType.java","lineNumber":75,"sourceCode":"\t}\n\n\tpublic SqlAstJoinType getCorrespondingSqlJoinType() {\n\t\treturn switch (this) {\n\t\t\tcase RIGHT -> SqlAstJoinType.RIGHT;\n\t\t\tcase LEFT -> SqlAstJoinType.LEFT;\n\t\t\tcase INNER -> SqlAstJoinType.INNER;\n\t\t\tcase FULL -> SqlAstJoinType.FULL;\n\t\t\tcase CROSS -> SqlAstJoinType.CROSS;\n\t\t};\n\t}\n\n\tpublic jakarta.persistence.criteria.JoinType getCorrespondingJpaJoinType() {\n\t\treturn switch (this) {\n\t\t\tcase RIGHT -> jakarta.persistence.criteria.JoinType.RIGHT;\n\t\t\tcase LEFT -> jakarta.persistence.criteria.JoinType.LEFT;\n\t\t\tcase INNER -> jakarta.persistence.criteria.JoinType.INNER;\n\t\t\tcase FULL -> jakarta.persistence.criteria.JoinType.FULL;\n\t\t\tdefault -> throw new IllegalArgumentException( \"Join type has no JPA join type mapping: \" + this );\n\t\t};\n\t}\n\n\tpublic JoinType getCorrespondingJoinType() {\n\t\treturn switch (this) {\n\t\t\tcase RIGHT -> JoinType.RIGHT;\n\t\t\tcase LEFT -> JoinType.LEFT;\n\t\t\tcase INNER -> JoinType.INNER;\n\t\t\tcase FULL -> JoinType.FULL;\n\t\t\tcase CROSS -> JoinType.CROSS;\n\t\t};\n\t}\n\n\tpublic static SqmJoinType from(JoinType joinType) {\n\t\treturn switch ( joinType ) {\n\t\t\tcase INNER -> INNER;\n\t\t\tcase LEFT -> LEFT;\n\t\t\tcase RIGHT -> RIGHT;","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/SqmJoinType.java#L57-L93","documentation":"SqmJoinType.getCorrespondingJpaJoinType() maps the SQM join kinds to jakarta.persistence.criteria.JoinType. RIGHT, LEFT, INNER and FULL have explicit mappings; SqmJoinType.CROSS has none and falls into the default branch, throwing IllegalArgumentException. So converting a cross join (created via crossJoin(...), see SqmCrossJoin.getSqmJoinType() == CROSS) to a JPA criteria join type always fails.","triggerScenarios":"Calling SqmJoinType.CROSS.getCorrespondingJpaJoinType() directly, or SQM-processing code (custom walkers, criteria copiers, renderers) doing sqmJoin.getSqmJoinType().getCorrespondingJpaJoinType() on a SqmCrossJoin or any join whose type is CROSS.","commonSituations":"Frameworks/tools that mirror an SQM tree into a jakarta criteria tree; adding crossJoin() to a query that such a tool then visits; upgrading code that previously only saw LEFT/INNER joins.","solutions":["Special-case CROSS before converting: render it as a plain inner join (cross join semantics) or handle it separately.","Use getCorrespondingJoinType() (org.hibernate.query.JoinType) instead, which supports CROSS.","Replace crossJoin(Class) with a regular join to an entity and an explicit join predicate when downstream code needs JPA join types."],"exampleFix":"// before\njakarta.persistence.criteria.JoinType jt = sqmJoin.getSqmJoinType().getCorrespondingJpaJoinType(); // throws for CROSS\n// after\njakarta.persistence.criteria.JoinType jt = sqmJoin.getSqmJoinType() == SqmJoinType.CROSS\n        ? jakarta.persistence.criteria.JoinType.INNER\n        : sqmJoin.getSqmJoinType().getCorrespondingJpaJoinType();","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static Optional<jakarta.persistence.criteria.JoinType> toJpaJoinType(SqmJoinType t) {\n    return t == SqmJoinType.CROSS\n        ? Optional.empty() // no JPA counterpart\n        : Optional.of( t.getCorrespondingJpaJoinType() );\n}","tryCatchPattern":null,"preventionTips":["In SQM visitors, branch on SqmCrossJoin (or getSqmJoinType() == CROSS) before converting join types.","Prefer getCorrespondingJoinType() (Hibernate's own JoinType) when CROSS must survive the mapping.","Model CROSS joins explicitly in your renderer (e.g. as comma-separated FROM entries or INNER without predicate)."],"tags":["hibernate","sqm","join","enum-mapping","cross-join"],"backgroundTag":"unsupported-enum-value","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}