hibernate/hibernate-orm · error · DuplicateMappingException
Duplicate table mapping '{}'
Error message
Duplicate table mapping '{}' What it means
DuplicateMappingException(Type.TABLE): the table-registration path (the snippet is the denormalized-table branch used by secondary tables and joined inheritance) found that a table with the same logical name already exists in the same catalog/schema namespace. Tables are keyed by (catalog, schema, name), so a collision means two mappings claim one table slot and bootstrap aborts.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java:962
// being set into the generated table (mainly to avoid later NPE), but for now we need to keep that :(
final Identifier logicalName = name != null ? database.toIdentifier( name ) : null;
if ( subselectFragment != null ) {
return namespace.createDenormalizedTable(
logicalName,
physicalName -> new DenormalizedTable(
buildingContext.getCurrentContributorName(),
namespace,
logicalName,
subselectFragment,
isAbstract,
includedTable
)
);
}
else {
if ( namespace.locateTable( logicalName ) != null ) {
assert logicalName != null;
throw new DuplicateMappingException( DuplicateMappingException.Type.TABLE, logicalName.toString() );
}
else {
return namespace.createDenormalizedTable(
logicalName,
physicalTableName -> new DenormalizedTable(
buildingContext.getCurrentContributorName(),
namespace,
physicalTableName,
isAbstract,
includedTable
)
);
}
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~View on GitHub (pinned to fad1729dce)
Solutions
- Rename one of the colliding tables: compare the name in the message against every @Table, @SecondaryTable and @JoinTable declaration
- Verify a PhysicalNamingStrategy is not making two different logical names equal after normalization
- Ensure joined subclasses do not restate the parent table's name
- Re-run bootstrap after the rename; table duplicates always fail the build
Example fix
// before — secondary table collides with the primary table @Entity @Table(name = "orders") @SecondaryTable(name = "orders", pkJoinColumns = @PrimaryKeyJoinColumn(name = "id")) // after @Entity @Table(name = "orders") @SecondaryTable(name = "order_details", pkJoinColumns = @PrimaryKeyJoinColumn(name = "order_id"))
Defensive patterns
Strategy: try-catch
Validate before calling
static void assertNoDuplicateTableNames( Class<?>... entityClasses ) {
final Set<String> seen = new HashSet<>();
for ( final Class<?> c : entityClasses ) {
final Table t = c.getAnnotation( Table.class );
if ( t != null && !seen.add( t.catalog() + '.' + t.schema() + '.' + t.name() ) ) {
throw new IllegalStateException( "Duplicate table name: " + t.name() + " on " + c );
}
for ( final SecondaryTable st : c.getAnnotationsByType( SecondaryTable.class ) ) {
if ( !seen.add( st.catalog() + '.' + st.schema() + '.' + st.name() ) ) {
throw new IllegalStateException( "Duplicate table name: " + st.name() + " on " + c );
}
}
}
} Try / catch
try {
sessionFactory = metadata.buildSessionFactory();
} catch ( DuplicateMappingException e ) {
if ( e.getType() == DuplicateMappingException.Type.TABLE ) {
throw new IllegalStateException( "Duplicate table mapping '" + e.getName() + "' — check @Table/@SecondaryTable/@JoinTable names and the naming strategy", e );
}
throw e;
} Prevention
- Keep table names unique across the whole persistence unit, not just per entity
- Review PhysicalNamingStrategy changes that add or strip prefixes
- Do not restate the parent table name on joined subclasses
- Include the complete entity set in the CI bootstrap test
When it happens
Trigger: A @SecondaryTable whose name equals the entity's primary @Table or another secondary table; joined-subclass hierarchies with explicitly colliding table names; naming-strategy normalization making two distinct declarations converge to one name.
Common situations: Copy-pasted entities, refactors that renamed a primary table onto an existing secondary/join table name, and PhysicalNamingStrategies that add/strip prefixes so different declarations collapse to the same physical name.
Related errors
- Duplicate named query '%s'
- Duplicate named stored procedure '{}'
- Duplicate SQL result set mapping '{}'
- Unable to find physical table: {}
- Table [%s] contains logical column name [%s] referring to mu
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/fd610111c4a37229.
Report an issue: GitHub.