How does hibernate generate foreign key constraint names?
If i do not define a name hibernate generates something like this
CONSTRAINT fk_2ocepcfwpr1v18dg1ieoe6bau
how is this name generated? Maybe from MD5
hash of field names or something like that? I need to know if the name is equal on all instances.
7.2. This foreign key is referred to as the collection key column, or columns, of the collection table. The collection key column is mapped by the @JoinColumn annotation respectively the <key> XML element. In annotations the Hibernate specific annotation @OnDelete has to be used.
You can use JPA's @MapsId annotation to tell Hibernate that it shall use the foreign key of an associated entity as the primary key. Let's take a look at a simple example. Each Book has a Manuscript, and each Manuscript belongs to 1 Book. The foreign key of the Book is also the primary key of the Manuscript.
MySQL requires that foreign key columns be indexed; if you create a table with a foreign key constraint but no index on a given column, an index is created.
Hibernate generates a constraint name by concatenating table and properties names and convert the result to MD5
. It is needed, because of the constraint names length restriction in some databases. For an example, in the Oracle database, a foreign key name length can't be more than 30 symbols length.
This code snippet from Hibernate source org.hibernate.mapping.Constraint
/**
* If a constraint is not explicitly named, this is called to generate
* a unique hash using the table and column names.
* Static so the name can be generated prior to creating the Constraint.
* They're cached, keyed by name, in multiple locations.
*
* @return String The generated name
*/
public static String generateName(String prefix, Table table, Column... columns) {
// Use a concatenation that guarantees uniqueness, even if identical names
// exist between all table and column identifiers.
StringBuilder sb = new StringBuilder( "table`" + table.getName() + "`" );
// Ensure a consistent ordering of columns, regardless of the order
// they were bound.
// Clone the list, as sometimes a set of order-dependent Column
// bindings are given.
Column[] alphabeticalColumns = columns.clone();
Arrays.sort( alphabeticalColumns, ColumnComparator.INSTANCE );
for ( Column column : alphabeticalColumns ) {
String columnName = column == null ? "" : column.getName();
sb.append( "column`" ).append( columnName ).append( "`" );
}
return prefix + hashedName( sb.toString() );
}
/**
* Hash a constraint name using MD5. Convert the MD5 digest to base 35
* (full alphanumeric), guaranteeing
* that the length of the name will always be smaller than the 30
* character identifier restriction enforced by a few dialects.
*
* @param s
* The name to be hashed.
* @return String The hased name.
*/
public static String hashedName(String s) {
try {
MessageDigest md = MessageDigest.getInstance( "MD5" );
md.reset();
md.update( s.getBytes() );
byte[] digest = md.digest();
BigInteger bigInt = new BigInteger( 1, digest );
// By converting to base 35 (full alphanumeric), we guarantee
// that the length of the name will always be smaller than the 30
// character identifier restriction enforced by a few dialects.
return bigInt.toString( 35 );
}
catch ( NoSuchAlgorithmException e ) {
throw new HibernateException( "Unable to generate a hashed Constraint name!", e );
}
}
You can generate your own constraint names (unique and foreign key) using ImplicitNamingStrategy
. You can refer Hibernate5NamingStrategy , as an example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With