{"record":{"id":"16bbe61d5916a885","repo":"hibernate/hibernate-orm","slug":"sql-strings-added-more-than-once-for","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/SchemaCreatorImpl.java","lineNumber":551,"sourceCode":"\t\t\t\t\t\tfinal Identifier schemaPhysicalName = context.schemaWithDefault( physicalName.schema() );\n\t\t\t\t\t\tif ( schemaPhysicalName != null ) {\n\t\t\t\t\t\t\tapplySqlStrings(\n\t\t\t\t\t\t\t\t\tdialect.getCreateSchemaCommand( schemaPhysicalName.render( dialect ) ),\n\t\t\t\t\t\t\t\t\tformatter,\n\t\t\t\t\t\t\t\t\toptions,\n\t\t\t\t\t\t\t\t\ttargets\n\t\t\t\t\t\t\t);\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/**\n\t * For testing...\n\t *\n\t * @param metadata The metadata for which to generate the creation commands.\n\t *\n\t * @return The generation commands\n\t */\n\t@Internal\n\tpublic List<String> generateCreationCommands(Metadata metadata, final boolean manageNamespaces) {\n\t\tfinal var target = new JournalingGenerationTarget();\n\t\tfinal var metadataImplementor = (MetadataImplementor) metadata;\n\t\tcreateFromMetadata(\n\t\t\t\tmetadata,\n\t\t\t\tnew ExecutionOptions() {","sourceCodeStart":533,"sourceCodeEnd":569,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaCreatorImpl.java#L533-L569","documentation":"During schema creation Hibernate walks every Exportable (table, sequence, UDT, index, auxiliary object) and records its export identifier; the identifier must be unique because each object's SQL may only be emitted once. When the same identifier is seen again, this SchemaManagementException aborts creation, naming the duplicated exportable. It almost always means one physical database object is mapped twice in the Metadata.","triggerScenarios":"Metadata in which the same exportable is registered twice: two @Entity classes mapped to the same table name, a class mapped both via annotations and via hbm.xml and both sources added, the same @AuxiliaryDatabaseObject defined twice, or programmatic Metadata building (InFlightMetadataCollector) that adds the same Table/Sequence/UDT object more than once. The throw happens while SchemaCreatorImpl.doCreation walks namespaces and calls checkExportIdentifier.","commonSituations":"Copy-paste refactors leaving two entities with the same @Table name; a mapping class added twice to MetadataSources (addAnnotatedClass + addResource of the same class); duplicate auxiliary/database objects in XML and annotations; merging metadata from multiple modules that overlap on the same table; persistence.xml listing the same class in two mapping-file entries.","solutions":["Take the identifier at the end of the message (e.g. my_table) and grep all mappings for that name; make each physical object mapped exactly once.","If two entities must target one table, keep a single owning entity mapping and access the second view via a query or a secondary/read-only mapping instead of duplicating the exportable.","Check MetadataSources/persistence.xml for the same annotated class or hbm.xml file added twice; check for auxiliary database objects defined in both annotations and XML.","After fixing, run SchemaExport with TargetType.STDOUT and confirm each object's DDL appears exactly once."],"exampleFix":"// before\n@Entity @Table(name = \"orders\")\npublic class Order { ... }\n\n@Entity @Table(name = \"orders\") // duplicate exportable for table `orders`\npublic class PurchaseOrder { ... }\n\n// after: give the second entity its own table\n@Entity @Table(name = \"purchase_orders\")\npublic class PurchaseOrder { ... }","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() : NamingStrategy.defaultName(entity);\n    if (!seen.add(name.toLowerCase(Locale.ROOT))) {\n        throw new IllegalStateException(\"Duplicate table mapping detected: \" + name);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    new SchemaExport(metadata).setOutputFile(\"ddl.sql\").createOnly();\n} catch (SchemaManagementException e) {\n    String m = e.getMessage();\n    if (m != null && m.startsWith(\"SQL strings added more than once for:\")) {\n        String exportable = m.substring(m.lastIndexOf(' ') + 1);\n        // grep mappings for `exportable`, remove the duplicate registration, rebuild Metadata\n    } else { throw e; }\n}","preventionTips":["Enforce unique table names with an ArchUnit/mapping-review test across all entities.","Never add the same mapping class or resource to MetadataSources twice; centralize source registration in one place.","Treat this error as a mapping bug; do not ignore or suppress it."],"tags":["hibernate","schema-generation","mapping","duplicate","ddl"],"backgroundTag":"duplicate-schema-object-mapping","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}