hibernate/hibernate-orm · error · MappingException

Unable to find physical table: {}

Error message

Unable to find physical table: {}

What it means

getLogicalTableName(Table) resolves a table object back to its logical name through the physical-to-logical map filled by addTableNameBinding. This MappingException means no binding was recorded for that physical name identifier — the Table was created or named outside the normal binding flow, or its Identifier differs (quoting or case) from the bound one.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java:1039

	public void addTableNameBinding(Identifier logicalName, Table table) {
		logicalToPhysicalTableNameMap.put( logicalName, table.getNameIdentifier() );
		physicalToLogicalTableNameMap.put( table.getNameIdentifier(), logicalName );
	}

	@Override
	public void addTableNameBinding(String schema, String catalog, String logicalName, String realTableName, Table denormalizedSuperTable) {
		final Identifier logicalNameIdentifier = getDatabase().toIdentifier( logicalName );
		final Identifier physicalNameIdentifier = getDatabase().toIdentifier( realTableName );

		logicalToPhysicalTableNameMap.put( logicalNameIdentifier, physicalNameIdentifier );
		physicalToLogicalTableNameMap.put( physicalNameIdentifier, logicalNameIdentifier );
	}

	@Override
	public String getLogicalTableName(Table ownerTable) {
		final Identifier logicalName = physicalToLogicalTableNameMap.get( ownerTable.getNameIdentifier() );
		if ( logicalName == null ) {
			throw new MappingException( "Unable to find physical table: " + ownerTable.getName() );
		}
		return logicalName.render();
	}

	@Override
	public String getPhysicalTableName(Identifier logicalName) {
		final Identifier physicalName = logicalToPhysicalTableNameMap.get( logicalName );
		return physicalName == null ? null : physicalName.render();
	}

	@Override
	public String getPhysicalTableName(String logicalName) {
		return getPhysicalTableName( getDatabase().toIdentifier( logicalName ) );
	}

	/**
	 * Internal struct used to maintain xref between physical and logical column
	 * names for a table.  Mainly this is used to ensure that the defined NamingStrategy

View on GitHub (pinned to fad1729dce)

Solutions

  1. Register every table through the collector (addTable plus addTableNameBinding) instead of constructing Table objects directly
  2. Make quoting consistent: quote a table name in all its mappings or in none
  3. Verify the PhysicalNamingStrategy yields identical physical names at bind time and at lookup time
  4. If a third-party contributor creates tables, align it with the collector's binding helpers or report the incompatibility upstream

Example fix

<!-- before: quoted in one place, unquoted in another -->
@Table(name = "`order`")
<!-- elsewhere -->
<join table="order">...

<!-- after: same quoting everywhere -->
@Table(name = "`order`")
<join table="`order`">...
Defensive patterns

Strategy: try-catch

Validate before calling

// verify a binding exists on the logical side before resolving physical tables
final String physical = metadata.getPhysicalTableName( logicalName );
if ( physical == null ) {
    throw new IllegalStateException( "No physical table bound for logical name: " + logicalName );
}

Try / catch

try {
    return mapping.getLogicalTableName( table );
} catch ( MappingException e ) {
    if ( e.getMessage() != null && e.getMessage().contains( "Unable to find physical table" ) ) {
        // table created outside addTableNameBinding, or quoting/case mismatch on the Identifier
        throw new IllegalStateException( "Table " + table.getName() + " never bound logically — register it via addTableNameBinding", e );
    }
    throw e;
}

Prevention

When it happens

Trigger: A Table instance constructed directly by custom code or a contributor instead of via the collector's addTable/addTableNameBinding; backtick-quoted names bound unquoted but looked up quoted (or vice versa); a PhysicalNamingStrategy producing different physical names at binding time versus lookup time.

Common situations: Custom MetadataContributors mixing programmatic tables with annotated mappings, switching PhysicalNamingStrategy mid-migration, and adding backtick quoting to some mappings but not others after moving to a case-sensitive database.

Related errors


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