hibernate/hibernate-orm · error · UnsupportedOperationException
Cannot add primary key constraint in Cloud Spanner.
Error message
Cannot add primary key constraint in Cloud Spanner.
What it means
SpannerDialect.getAddPrimaryKeyConstraintString() throws UnsupportedOperationException because Cloud Spanner does not support ALTER TABLE ... ADD PRIMARY KEY — a primary key must be declared inline in CREATE TABLE. This guard fires whenever Hibernate's schema migrator tries to emit an add-PK alter statement, which on Spanner is always invalid. It signals a mapping/tooling path that expects additive DDL Spanner cannot perform.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/dialect/SpannerDialect.java:1215
public String getCurrentSchemaCommand() {
throw new UnsupportedOperationException(
"No current schema syntax supported by " + getClass().getName() );
}
@Override
public SchemaNameResolver getSchemaNameResolver() {
// Spanner does not have a notion of database name schemas, so return "".
return (connection, dialect) -> "";
}
@Override
public boolean qualifyIndexName() {
return false;
}
@Override
public String getAddPrimaryKeyConstraintString(String constraintName) {
throw new UnsupportedOperationException( "Cannot add primary key constraint in Cloud Spanner." );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Lock acquisition functions
@Override
public LockingSupport getLockingSupport() {
return SPANNER_LOCKING_SUPPORT;
}
@Override
public LockingClauseStrategy getLockingClauseStrategy(QuerySpec querySpec, LockOptions lockOptions) {
if ( getPessimisticLockStyle() != PessimisticLockStyle.CLAUSE || lockOptions == null ) {
return NON_CLAUSE_STRATEGY;
}
final var lockKind = PessimisticLockKind.interpret( lockOptions.getLockMode() );
if ( lockKind == PessimisticLockKind.NONE ) {
return NON_CLAUSE_STRATEGY;View on GitHub (pinned to fad1729dce)
Solutions
- Ensure every @Entity declares @Id/@EmbeddedId so the CREATE TABLE generated for Spanner includes PRIMARY KEY inline, and recreate the table rather than altering it.
- Replace hbm2ddl schema update with explicit migrations using Cloud Spanner DDL (CREATE TABLE ... PRIMARY KEY (...)) via the Spanner migration tooling.
- If you are issuing alters programmatically, check `dialect.getAddPrimaryKeyConstraintString` availability or skip PK alters for Spanner before calling.
- For existing tables needing a new key, create a new table, copy data, and swap — Spanner cannot retrofit a PK.
Example fix
// before: migrate later with alter
// alter table orders add constraint pk_orders primary key (id) -- Unsupported
// after: key declared inline at create time
@Entity
public class Order {
@Id String id;
...
}
// -> create table orders (id string not null, ..., ) primary key (id) Defensive patterns
Strategy: fallback
Validate before calling
if (dialect instanceof SpannerDialect) {
// verify PK exists inline in table DDL instead of planning an ALTER
Table t = metadata.getEntityBinding(Entity.class.getName()).getTable();
if (t.getPrimaryKey() == null || t.getPrimaryKey().columnSpan() == 0) {
throw new IllegalStateException("Spanner requires PRIMARY KEY inline in CREATE TABLE for " + t.getName());
}
} Try / catch
try {
migrator.performMigration(migration, executionOptions, target);
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("primary key")) { /* recreate table with inline PK and copy data instead */ }
throw e;
} Prevention
- Always declare @Id/@EmbeddedId so CREATE TABLE includes PRIMARY KEY on Spanner.
- Use explicit Spanner migrations rather than hbm2ddl update.
- Remember PKs cannot be retrofitted on Spanner — plan keys up front.
When it happens
Trigger: SchemaUpdate/hbm2ddl alter passes where an entity lacks an inline PK at create time or a constraint is added later (e.g. `@PrimaryKeyJoinColumn` handling or manual AlterTable commands); executing `new SchemaMigrator()` that generates 'alter table T add constraint ... primary key' against Spanner; secondary mapping mistakes where the key is not part of the CREATE TABLE definition.
Common situations: Running hibernate.hbm2ddl.auto=update on evolving Spanner schemas; migrations authored for databases that permit deferred PK addition; entities whose identifier is only discovered as a constraint by the tooling rather than declared in the table DDL.
Related errors
- No add primary key syntax supported by SQLiteDialect
- SingleStore does not support altering primary key.
- "No create schema syntax supported by " + getClass().getName
- "No drop schema syntax supported by " + getClass().getName()
- No drop foreign key syntax supported by SQLiteDialect
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/09aa64174a628f18.
Report an issue: GitHub.