hibernate/hibernate-orm · error · IllegalStateException

Assignment referred to columns from multiple tables

Error message

Assignment referred to columns from multiple tables

What it means

When an INSERT runs through the CTE-based multi-table strategy (joined/union inheritance or secondary tables), CteInsertHandler buckets each assignment by table. Every column of a single assignment must belong to ONE table; if the assignment's column references resolve to different table references, this IllegalStateException fires during SQM-to-SQL translation. The in-code TODO ('could be fixed by introducing joins to DML statements') marks it as a known structural limitation.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteInsertHandler.java:687

		final Map<TableReference, List<Map.Entry<List<CteColumn>, Assignment>>> assignmentsByTable = CollectionHelper.mapOfSize(
				updatingTableGroup.getTableReferenceJoins().size() + 1
		);

		for ( int i = 0; i < assignments.size(); i++ ) {
			final Map.Entry<List<CteColumn>, Assignment> entry = assignments.get( i );
			final Assignment assignment = entry.getValue();
			final List<ColumnReference> assignmentColumnRefs = assignment.getAssignable().getColumnReferences();

			TableReference assignmentTableReference = null;

			for ( int c = 0; c < assignmentColumnRefs.size(); c++ ) {
				final ColumnReference columnReference = assignmentColumnRefs.get( c );
				final TableReference tableReference = resolveTableReference( columnReference, tableReferenceByAlias );

				// TODO: this could be fixed by introducing joins to DML statements
				if ( assignmentTableReference != null && !assignmentTableReference.equals( tableReference ) ) {
					throw new IllegalStateException( "Assignment referred to columns from multiple tables" );
				}

				assignmentTableReference = tableReference;
			}
			assert assignmentTableReference != null;

			List<Map.Entry<List<CteColumn>, Assignment>> assignmentsForTable = assignmentsByTable.get( assignmentTableReference );
			if ( assignmentsForTable == null ) {
				assignmentsForTable = new ArrayList<>();
				assignmentsByTable.put( assignmentTableReference, assignmentsForTable );
			}
			assignmentsForTable.add( entry );
		}


		// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Add the root insert as cte

View on GitHub (pinned to fad1729dce)

Solutions

  1. Restructure the mapping so each embedded/attribute maps to columns of a single table
  2. Simplify the insert target list to scalar single-table attributes
  3. Remove the forced CTE strategy and let Hibernate use the table-based handler
  4. Upgrade to the latest 6.x patch release and search Hibernate JIRA for 'Assignment referred to columns from multiple tables'; file an issue with a reproducer if the mapping is valid

Example fix

// mapping: @Embedded spanning primary + secondary table
// before
@Embedded Details details; // columns in both MAIN and SEC tables

// after: split into two embeddables, one per table
@Embedded MainDetails mainDetails;
@Embedded SecondaryDetails secondaryDetails;
Defensive patterns

Strategy: try-catch

Validate before calling

// Before bulk insert on multi-table entities, assert each target attribute maps to one table
// (heuristic: avoid embeddables mixing primary- and secondary-table columns in the target list)
if (targetAttrs.stream().anyMatch(a -> a.isEmbedded())) {
    log.warn("Embedded target attribute may span tables — test this insert against the CTE strategy");
}

Try / catch

try {
    em.createQuery(insertHql).executeUpdate();
} catch (IllegalStateException e) {
    if (e.getMessage().contains("multiple tables")) {
        throw new MappingIssueException(
            "Assignment spans tables — split the insert or simplify the mapping: " + insertHql, e);
    }
    throw e;
}

Prevention

When it happens

Trigger: HQL `insert into` on an entity handled by CteInsertStrategy where one assignment is an embedded/composite or otherwise maps columns into more than one table (e.g. an @Embedded with members in both the primary and a @SecondaryTable); assignments backed by formulas spanning tables.

Common situations: Entities with @SecondaryTable whose component attributes split across tables; forcing `hibernate.query.mutation_strategy=cte` for insert...select performance and then hitting an unsupported mapping; Hibernate 6.x regressions in CTE insert handling — several JIRA issues match this invariant.

Related errors


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