{"record":{"id":"fec7170d71f928d6","repo":"hibernate/hibernate-orm","slug":"sql-strings-added-more-than-once-for-fec717","errorCode":null,"errorMessage":"SQL strings added more than once for: ","messagePattern":"SQL strings added more than once for: ","errorType":"exception","errorClass":"SchemaManagementException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaTruncatorImpl.java","lineNumber":232,"sourceCode":"\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\telse if ( !dialect.canBatchTruncate() ) {\n\t\t\t\t\t\tapplySqlStrings(\n\t\t\t\t\t\t\t\tdialect.getForeignKeyExporter().getSqlCreateStrings( foreignKey, metadata, context ),\n\t\t\t\t\t\t\t\tformatter,\n\t\t\t\t\t\t\t\toptions,\n\t\t\t\t\t\t\t\ttargets\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate static void checkExportIdentifier(Exportable exportable, Set<String> exportIdentifiers) {\n\t\tfinal String exportIdentifier = exportable.getExportIdentifier();\n\t\tif ( exportIdentifiers.contains( exportIdentifier ) ) {\n\t\t\tthrow new SchemaManagementException( \"SQL strings added more than once for: \" + exportIdentifier );\n\t\t}\n\t\texportIdentifiers.add( exportIdentifier );\n\t}\n\n\t@Override\n\tClassLoaderService getClassLoaderService() {\n\t\treturn tool.getServiceRegistry().getService( ClassLoaderService.class );\n\t}\n\n}\n","sourceCodeStart":214,"sourceCodeEnd":243,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaTruncatorImpl.java#L214-L243","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n@Entity @Table(name = \"cart_items\")\npublic class CartItem { ... }\n@Entity @Table(name = \"cart_items\")\npublic class LegacyCartItem { ... }\n\n// after\n@Entity @Table(name = \"cart_items\")\npublic class CartItem { ... }\n// second mapping deleted; reads of legacy rows go through a native query","handlingStrategy":"validation","validationCode":"Set<String> seen = new HashSet<>();\nfor (Class<?> entity : mappedEntities) {\n    Table t = entity.getAnnotation(Table.class);\n    String name = (t != null && !t.name().isEmpty()) ? t.name() : entity.getSimpleName();\n    if (!seen.add(name.toLowerCase(Locale.ROOT))) {\n        throw new IllegalStateException(\"Duplicate table mapping detected: \" + name);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    schemaManagementTool.getSchemaTruncator(settings).doTruncate(metadata, options, targetDescriptor);\n} catch (SchemaManagementException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"SQL strings added more than once for:\")) {\n        String exportable = e.getMessage().substring(e.getMessage().lastIndexOf(' ') + 1);\n        // remove the duplicate mapping for `exportable`, then truncate again\n    } else { throw e; }\n}","preventionTips":["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."],"tags":["hibernate","schema-generation","mapping","duplicate","truncate","ddl"],"backgroundTag":"duplicate-schema-object-mapping","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}