生成重复的唯一约束名称

Generation of duplicate unique constraint names

在为域 class 定义唯一约束时,grails 会为数据库生成一个基于 属性 名称的约束名称。 当使用 Postgres 作为数据库时,对于以下约束定义,名称将为 'unique_language'。

   static constraints = {
      language nullable: false, unique: 'product'
   }

当我现在有了第二个域 class,它对同名 属性 也有唯一约束时,grails 将再次创建一个名为 'unique_language' 的数据库约束. 问题是,对于 Postgres,唯一约束的名称对于数据库模式也必须是唯一的。这意味着在我们的例子中,第二个 约束未应用于数据库。

有没有办法自定义或定义唯一索引名称?

我正在寻找是否可以增强 NamingStrategy,但我找不到可以进行更改的地方。

我们目前使用的是 grails 2.4.4

此问题已在 Grails 3.1.0.RC2 中修复:https://github.com/grails/grails-data-mapping/issues/623

我们在我们的案例中使用的是 grails 2.4.4,因此现在实施了一个解决方法。

我们实现了一种继承自 class org.hibernate.dialect.PostgreSQL9Dialect 的新方言。

新方言 class 的唯一变化是分配了一个名为 PostgresUniqueDelegate 的自定义 UnitqueDelegate。 class 继承自 org.hibernate.dialect.unique.DefaultUniqueDelegate 并覆盖约束生成方法。

class PostgresSQL9DialectUniqueConstraints extends PostgreSQL9Dialect {

    private final UniqueDelegate uniqueDelegate

    PostgresSQL9DialectUniqueConstraints() {
        super()
        uniqueDelegate = new PostgresUniqueDelegate(this)
    }

    @Override
    UniqueDelegate getUniqueDelegate() {
        return uniqueDelegate
    }

}

这是 PostgresUniqueDelegate 的代码 class

class PostgresUniqueDelegate extends DefaultUniqueDelegate {

    PostgresUniqueDelegate(Dialect dialect) {
        super(dialect)
    }

    private final PREFIX = "unique_"

    private String getCustomUniqueKey(String uniqueKeyName, String tableName) {
        return uniqueKeyName.replaceAll(PREFIX, PREFIX + tableName + "_")
    }

    @Override
    String getAlterTableToAddUniqueKeyCommand(
            org.hibernate.mapping.UniqueKey uniqueKey,
            String defaultCatalog,
            String defaultSchema)
    {
        // Do this here, rather than allowing UniqueKey/Constraint to do it.
        // We need full, simplified control over whether or not it happens.
        final String tableName = uniqueKey.getTable().getQualifiedName(dialect, defaultCatalog, defaultSchema)
        final String constraintName = dialect.quote(getCustomUniqueKey(uniqueKey.getName(), tableName))
        return "alter table " + tableName + " add constraint " + constraintName + " " + uniqueConstraintSql(uniqueKey)
    }

    @Override
    String getAlterTableToAddUniqueKeyCommand(UniqueKey uniqueKey) {
        // Do this here, rather than allowing UniqueKey/Constraint to do it.
        // We need full, simplified control over whether or not it happens.
        final String tableName = uniqueKey.getTable().getQualifiedName(dialect)
        final String constraintName = dialect.quote(getCustomUniqueKey(uniqueKey.getName(), tableName))

        return "alter table " + tableName + " add constraint " + constraintName + uniqueConstraintSql(uniqueKey);
    }

}