hibernate/hibernate-orm · error · SchemaManagementException

SQL strings added more than once for:

Error message

SQL strings added more than once for: 

What it means

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.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaCreatorImpl.java:551

						final Identifier schemaPhysicalName = context.schemaWithDefault( physicalName.schema() );
						if ( schemaPhysicalName != null ) {
							applySqlStrings(
									dialect.getCreateSchemaCommand( schemaPhysicalName.render( dialect ) ),
									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 );
	}

	/**
	 * For testing...
	 *
	 * @param metadata The metadata for which to generate the creation commands.
	 *
	 * @return The generation commands
	 */
	@Internal
	public List<String> generateCreationCommands(Metadata metadata, final boolean manageNamespaces) {
		final var target = new JournalingGenerationTarget();
		final var metadataImplementor = (MetadataImplementor) metadata;
		createFromMetadata(
				metadata,
				new ExecutionOptions() {

View on GitHub (pinned to fad1729dce)

Solutions

  1. 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.
  2. 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.
  3. 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.
  4. After fixing, run SchemaExport with TargetType.STDOUT and confirm each object's DDL appears exactly once.

Example fix

// before
@Entity @Table(name = "orders")
public class Order { ... }

@Entity @Table(name = "orders") // duplicate exportable for table `orders`
public class PurchaseOrder { ... }

// after: give the second entity its own table
@Entity @Table(name = "purchase_orders")
public class PurchaseOrder { ... }
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() : NamingStrategy.defaultName(entity);
    if (!seen.add(name.toLowerCase(Locale.ROOT))) {
        throw new IllegalStateException("Duplicate table mapping detected: " + name);
    }
}

Try / catch

try {
    new SchemaExport(metadata).setOutputFile("ddl.sql").createOnly();
} catch (SchemaManagementException e) {
    String m = e.getMessage();
    if (m != null && m.startsWith("SQL strings added more than once for:")) {
        String exportable = m.substring(m.lastIndexOf(' ') + 1);
        // grep mappings for `exportable`, remove the duplicate registration, rebuild Metadata
    } else { throw e; }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/16bbe61d5916a885. Report an issue: GitHub.