hibernate/hibernate-orm · error · SchemaManagementException
SQL strings added more than once for:
Error message
SQL strings added more than once for:
What it means
The truncate path (SchemaManagementTool.getSchemaTruncator(...).doTruncate) enforces the same one-SQL-per-exportable invariant as create and drop: each Exportable's identifier may be processed only once. A second registration of the same table/sequence/UDT aborts truncation with this SchemaManagementException naming the duplicated object.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaTruncatorImpl.java:232
);
}
else if ( !dialect.canBatchTruncate() ) {
applySqlStrings(
dialect.getForeignKeyExporter().getSqlCreateStrings( foreignKey, metadata, context ),
formatter,
options,
targets
);
}
}
}
}
}
private static void checkExportIdentifier(Exportable exportable, Set<String> exportIdentifiers) {
final String exportIdentifier = exportable.getExportIdentifier();
if ( exportIdentifiers.contains( exportIdentifier ) ) {
throw new SchemaManagementException( "SQL strings added more than once for: " + exportIdentifier );
}
exportIdentifiers.add( exportIdentifier );
}
@Override
ClassLoaderService getClassLoaderService() {
return tool.getServiceRegistry().getService( ClassLoaderService.class );
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Grep mappings for the identifier in the message and remove the duplicate registration so the object is mapped once.
- Rename intentional same-name objects (view vs table) so export identifiers differ.
- Audit MetadataSources/persistence.xml for the same class or resource added twice before building the Metadata used for truncation.
Example fix
// before
@Entity @Table(name = "cart_items")
public class CartItem { ... }
@Entity @Table(name = "cart_items")
public class LegacyCartItem { ... }
// after
@Entity @Table(name = "cart_items")
public class CartItem { ... }
// second mapping deleted; reads of legacy rows go through a native query Defensive patterns
Strategy: validation
Validate before calling
Set<String> seen = new HashSet<>();
for (Class<?> entity : mappedEntities) {
Table t = entity.getAnnotation(Table.class);
String name = (t != null && !t.name().isEmpty()) ? t.name() : entity.getSimpleName();
if (!seen.add(name.toLowerCase(Locale.ROOT))) {
throw new IllegalStateException("Duplicate table mapping detected: " + name);
}
} Try / catch
try {
schemaManagementTool.getSchemaTruncator(settings).doTruncate(metadata, options, targetDescriptor);
} catch (SchemaManagementException e) {
if (e.getMessage() != null && e.getMessage().startsWith("SQL strings added more than once for:")) {
String exportable = e.getMessage().substring(e.getMessage().lastIndexOf(' ') + 1);
// remove the duplicate mapping for `exportable`, then truncate again
} else { throw e; }
} Prevention
- Validate unique table names in a mapping test before wiring truncation into test fixtures.
- Register mapping sources once, centrally.
- Log the failing export identifier so fixture cleanup code can report exactly which mapping regressed.
When it happens
Trigger: Truncating schema (JPA schema-generation truncate action or the SchemaTruncator API) over Metadata that maps the same exportable twice: duplicate entity table names, a class registered both annotated and via XML, duplicated auxiliary database objects, or overlapping MetadataSources merged programmatically.
Common situations: Test fixtures that truncate between test classes and hit a refactoring artifact where two entities share a table name; module merges that map the same table from two jars; auxiliary objects defined redundantly in annotations and XML.
Related errors
- SQL strings added more than once for:
- SQL strings added more than once for:
- unknown type: {sqlTypeCode}
- Error creating SQL 'create' commands for table '
- '@GeneratedColumn' may only be applied to single-column mapp
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/fec7170d71f928d6.
Report an issue: GitHub.