hibernate/hibernate-orm · error · DuplicateMappingException

Table [%s] contains logical column name [%s] referring to mu

Error message

Table [%s] contains logical column name [%s] referring to multiple physical column names: [%s], [%s]

What it means

Inside one table's column-binding registry, the same logical column name was bound to a second physical name that differs (the comparison is case-insensitive unless the logical name is quoted). Hibernate keeps exactly one logical-to-physical mapping per table, so the conflicting binding raises DuplicateMappingException(Type.COLUMN_BINDING) and bootstrap stops.

Source

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

		private TableColumnNameBinding(String tableName) {
			this.tableName = tableName;
		}

		public void addBinding(Identifier logicalName, Column physicalColumn) {
			final String physicalNameString = physicalColumn.getQuotedName( getDialect() );
			bindLogicalToPhysical( logicalName, physicalNameString );
			bindPhysicalToLogical( logicalName, physicalNameString );
		}

		private void bindLogicalToPhysical(Identifier logicalName, String physicalName) throws DuplicateMappingException {
			final String existingPhysicalNameMapping = logicalToPhysical.put( logicalName, physicalName );
			if ( existingPhysicalNameMapping != null ) {
				final boolean areSame = logicalName.isQuoted()
						? physicalName.equals( existingPhysicalNameMapping )
						: physicalName.equalsIgnoreCase( existingPhysicalNameMapping );
				if ( !areSame ) {
					throw new DuplicateMappingException(
							String.format(
									Locale.ENGLISH,
									"Table [%s] contains logical column name [%s] referring to multiple physical " +
											"column names: [%s], [%s]",
									tableName,
									logicalName,
									existingPhysicalNameMapping,
									physicalName
							),
							DuplicateMappingException.Type.COLUMN_BINDING,
							tableName + "." + logicalName
					);
				}
			}
		}

		private void bindPhysicalToLogical(Identifier logicalName, String physicalName) throws DuplicateMappingException {
			final Identifier existingLogicalName = physicalToLogical.put( physicalName, logicalName );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Make the physical names identical — and identically quoted — for the logical name shown in the message
  2. Remove the redundant second mapping of that logical column
  3. Keep @AttributeOverride values for the same inherited attribute consistent across the hierarchy
  4. Use a single mapping style (annotations or hbm.xml) per hierarchy so columns are not bound twice

Example fix

// before: inherited attribute overridden to two different physical columns
@AttributeOverride(name = "startDate", column = @Column(name = "start_date")) // subclass A
@AttributeOverride(name = "startDate", column = @Column(name = "begin_date")) // subclass B, same table

// after: one physical column for the logical name
@AttributeOverride(name = "startDate", column = @Column(name = "start_date")) // both subclasses
Defensive patterns

Strategy: try-catch

Validate before calling

static void assertNoConflictingColumnOverrides( Class<?> root ) {
    final Map<String, String> logicalToPhysical = new HashMap<>();
    for ( Class<?> c = root; c != null && c != Object.class; c = c.getSuperclass() ) {
        for ( final Field f : c.getDeclaredFields() ) {
            final Column col = f.getAnnotation( Column.class );
            if ( col == null || col.name().isEmpty() ) {
                continue;
            }
            final String prev = logicalToPhysical.put( f.getName(), col.name() );
            if ( prev != null && !prev.equalsIgnoreCase( col.name() ) ) {
                throw new IllegalStateException( "Field '" + f.getName() + "' bound to two physical columns: " + prev + " and " + col.name() );
            }
        }
    }
}

Try / catch

try {
    sessionFactory = metadata.buildSessionFactory();
} catch ( DuplicateMappingException e ) {
    if ( e.getType() == DuplicateMappingException.Type.COLUMN_BINDING
            && e.getMessage() != null && e.getMessage().contains( "multiple physical" ) ) {
        // one logical column name in the named table maps to two different physical columns
        throw new IllegalStateException( "Conflicting column binding: " + e.getMessage(), e );
    }
    throw e;
}

Prevention

When it happens

Trigger: The same logical attribute of one table mapped twice with different @Column names — attribute overrides in an inheritance hierarchy remapping an inherited attribute to a different physical column; duplicated column declarations between hbm.xml and annotations; one binding quoted and the other not so the names compare unequal.

Common situations: Inheritance hierarchies with per-subclass @AttributeOverride, embeddables reused with different overrides inside one table, and mixes of annotation and XML mappings for a single hierarchy; migrations that renamed a column in only part of the mappings.

Related errors


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