Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

There exists a proprietary hibernate annotation to specify the Foreign Key constraint names that are used at DDL generation time: org.hibernate.annotations.ForeignKey.

Is there also a way to specify the Primary Key constraint names?

like image 522
Jan Avatar asked Jul 20 '10 10:07

Jan


People also ask

What are the valid criteria to choose a primary key in Hibernate?

You just need to add an attribute to your entity, make sure that its type and name match the database column, annotate it with @Column and you're done. You can then use the primary key to load the entity, and Hibernate sets the primary key value automatically.

Which method in JPA is used to retrieve the entity based on its primary keys?

The find() method used to retrieve an entity defined as below in the EntityManager interface. T find(Class<T> entityClass, Object primaryKey) – Returns entity for the given primary key. It returns null if entity is not found in the database.

What is unique constraint in JPA?

A unique constraint can be either a column constraint or a table constraint. At the table level, we can define unique constraints across multiple columns. JPA allows us to define unique constraints in our code using @Column(unique=true) and @UniqueConstraint.


2 Answers

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.

like image 161
Pascal Thivent Avatar answered Oct 23 '22 21:10

Pascal Thivent


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)
);
like image 28
Lance Avatar answered Oct 23 '22 21:10

Lance