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
- Make the physical names identical — and identically quoted — for the logical name shown in the message
- Remove the redundant second mapping of that logical column
- Keep @AttributeOverride values for the same inherited attribute consistent across the hierarchy
- 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
- Keep @AttributeOverride values for an inherited attribute identical across the hierarchy
- Use exactly one mapping style per hierarchy to avoid double column binding
- Match quoting when repeating column names
- Review column renames across all mappings, not just the entity that owns the column
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
- Table [%s] contains physical column name [%s] referred to by
- Duplicate named query '%s'
- Duplicate named stored procedure '{}'
- Duplicate SQL result set mapping '{}'
- Duplicate table mapping '{}'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/64245964aa62c83c.
Report an issue: GitHub.