hibernate如何生成外键约束名?

Posted

技术标签:

【中文标题】hibernate如何生成外键约束名?【英文标题】:How does hibernate generate foreign key constraint names? 【发布时间】:2016-08-14 11:48:53 【问题描述】:

如果我没有定义名称,hibernate 会生成类似这样的内容

CONSTRAINT fk_2ocepcfwpr1v18dg1ieoe6bau

这个名字是怎么产生的?也许来自MD5 字段名称的哈希或类似的东西?我需要知道名称是否在所有实例上都相同。

【问题讨论】:

【参考方案1】:

Hibernate 通过连接表名和属性名生成一个约束名,并将结果转换为MD5。由于某些数据库中的约束名称长度限制,因此需要它。例如,在 Oracle 数据库中,外键名称长度不能超过 30 个符号长度。

这段代码sn-p来自Hibernate源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 );
    

您可以使用ImplicitNamingStrategy 生成自己的约束名称(唯一和外键)。你可以参考Hibernate5NamingStrategy ,例如。

【讨论】:

以上是关于hibernate如何生成外键约束名?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Hibernate 注释标记外键约束?

Hibernate:无法添加或更新子行:外键约束失败

Hibernate 无法添加外键约束

在SQL中如何创建外键约束?

SQL 怎样删除有外键约束的表

Flyway 和 MariaDB:SQLException 外键约束的格式不正确