在 Grails (GORM) 中,如何覆盖约束名称

In Grails (GORM), how to override a constraint name

Grails (GORM) 中,如何覆盖约束名称(在生成的 dbm 脚本中)。我将 Oracle 与 GORM 一起使用。 约束名称的长度似乎限制为 15。

如果无法覆盖,那么有没有办法将长度更改为超过 15(比如 25)!!

例如

CREATE TABLE X ( 
       id NUMBER(19,0) NOT NULL, 
       CONSTRAINT overridden_name_here 
       PRIMARY KEY (id));   

不确定最新的 Grails 3 是否提供了更直接的自定义约束名称的方法,但在 Grails 2.4.5 和更早版本中,方法是使用自定义配置 subclass.

它主要涉及通过扩展 GrailsAnnotationConfiguration 和重写 secondPassCompile() 方法来创建您自己的配置。在这种方法中,您可以访问您的域 class 和 access/set 许多不同的属性,包括诸如外键约束名称之类的东西。

有关详细示例,请参阅 Burt Beckwith 的 post:http://burtbeckwith.com/blog/?p=465

我相信约束名称的长度限制是由底层数据库实现决定的,而不是 GORM 本身。

在 Grails 3 中,如果您正在使用 Hibernate 4.x,您只需要扩展 class HibernateMappingContextConfiguration 并覆盖 secondPassCompile 方法自定义外键名。但是,如果你想使用 Hibernate 5,解决方案会略有不同。查看 graeme 在 slack grails-community 上的评论:

Not our fault. Hibernate 5 is significantly different so we had to adapt. They essentially deprecated the Configuration hierarchy as well as changed how you hook into metadata. For Hibernate 5.2 this is going to have to change again.

所以,为了解决这个与 Hibernate 5 和 Grails 3 相关的问题,我做了下面的实现。首先我们需要覆盖默认的休眠实现:

import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.ImplicitForeignKeyNameSource;
import org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl;

public class ReadableImplicitNamingStrategy extends ImplicitNamingStrategyJpaCompliantImpl {

    public static final ReadableImplicitNamingStrategy INSTANCE = new ReadableImplicitNamingStrategy();

    private String getPlural(String tableName) {

        final int len = tableName.length();
        final boolean isLower = Character.isLowerCase(tableName.charAt(len - 1));
        final String s = tableName.toLowerCase();
        final char lastChar = s.charAt(len - 1);

        String result = tableName;

        switch (lastChar) {
            case 'y':
                result = tableName.substring(0, tableName.length() -1) + (isLower? "ie": "IE"); break;
            case 's':
            case 'x':
            case 'z':
                result = tableName.substring(0, tableName.length() -1) + (isLower? "e": "E"); break;
            default:
                if (s.endsWith("sh")) {
                    result = tableName.substring(0, tableName.length() -1) + (isLower? "e": "E");
                }
        }
        result += (isLower? "s": "S");
        return result;
    }

    @Override
    public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source) {

        StringBuilder sb = new StringBuilder("FK_")
                .append(source.getReferencedTableName().getText())
                .append("_")
                .append(getPlural(source.getTableName().getText()));

        return toIdentifier(sb.toString(), source.getBuildingContext());

    }
}

此外,我们必须创建一个 class 来自定义 Gorm 配置:

import org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration

    class GormConfiguration extends HibernateMappingContextConfiguration {

        @Override
        protected void reset() {
            super.reset();
            this.implicitNamingStrategy = ReadableImplicitNamingStrategy.INSTANCE;
        }

    }

最后,在我们的 application.yml 中引用我们将在数据源中使用的自定义 class。

dataSource:
    dbCreate: update
    configClass: mypackage.GormConfiguration