生成重复的唯一约束名称
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);
}
}
在为域 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);
}
}