How to choose DDL Primary Key constraint names with JPA/Hibernate

You can control the generated PK constraint names with a few small mods in a custom dialect. For example, here's how to do it in Oracle (the same approach works for SQLServer & DB2):

public class CustomOracleDialect extends org.hibernate.dialect.Oracle10gDialect {

   private CustomTableExporter customTableExporter;

   public CustomOracleDialect () {
     super();
     customTableExporter = new CustomTableExporter(this);
   }

   @Override
   public Exporter<Table> getTableExporter () {
     return customTableExporter;
   }

   static class CustomTableExporter extends StandardTableExporter {
     private final static int MAX_TABLE_NAME_LENGTH = 30;

     public CustomTableExporter (Dialect dialect) {
        super(dialect);
     }

     @Override
     public String[] getSqlCreateStrings (Table table, Metadata metadata) {
        final String[] sqlCreateStrings = super.getSqlCreateStrings(table, metadata);

        //-- replace " primary key" with " constraint TABLE_NAME_PK primary key "

        final String namedPkConstraint = " constraint " + StringUtils.truncate(table.getName(), MAX_TABLE_NAME_LENGTH - 3) + "_PK primary key ";

        for (int i = 0; i < sqlCreateStrings.length; ++i) {
           sqlCreateStrings[i] = StringUtils.replace(sqlCreateStrings[i], " primary key ", namedPkConstraint);
        }

        return sqlCreateStrings;
     }
   }
}

This will change the generated DDL from this:

-- BEFORE: 
create table FOO_ENTITY (
  FOO_ENTITY_ID number(19, 0)      not null,
  JOB_NAME      varchar2(128 char) not null,
  primary key (FOO_ENTITY_ID)
);

To this :

-- AFTER: 
create table FOO_ENTITY (
  FOO_ENTITY_ID number(19, 0)      not null,
  JOB_NAME      varchar2(128 char) not null,
  constraint FOO_ENTITY_PK primary key (FOO_ENTITY_ID)
);

The class org.hibernate.mapping.PrimaryKey does the following:

public String sqlConstraintString(Dialect dialect) {
    StringBuilder buf = new StringBuilder("primary key (");
    Iterator iter = getColumnIterator();
    while ( iter.hasNext() ) {
        buf.append( ( (Column) iter.next() ).getQuotedName(dialect) );
        if ( iter.hasNext() ) {
            buf.append(", ");
        }
    }
    return buf.append(')').toString();
}

The solution would be to override this method and return a string starting with "constraint YOUR_CONSTRAINT_NAME primary key" to make it possible. Unfortunately there's no way of overriding this.


Not possible with standard JPA and not supported by Hibernate for Primary Key constraints neither.

There is actually a very old issue about this feature request (HB-1245) but it looks like it doesn't get much attention.