Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

grails-orm

In Grails (GORM), how to override a constraint name (in the generated dbm script). I am using Oracle with GORM. It seems the length of the constraint name is restricted to 15.

If there's no way to override then is there a way to alter the length to more than 15 (say 25)!!

e.g.

CREATE TABLE X ( 
       id NUMBER(19,0) NOT NULL, 
       CONSTRAINT overridden_name_here 
       PRIMARY KEY (id));   
like image 944
Gautam Saggar Avatar asked Apr 06 '15 01:04

Gautam Saggar


2 Answers

In Grails 3, if you are using Hibernate 4.x you just need extend the class HibernateMappingContextConfiguration and override the secondPassCompile method to customize the foreign key names. However if you want use Hibernate 5, the solution is slightly different. See the graeme's comment on the 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.

So, to solve this problem related to Hibernate 5 and Grails 3, I did the implementation below. First we need to override the default hibernate implementation:

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());

    }
}

Also, we have to create a class to customize the Gorm Configuration:

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

    class GormConfiguration extends HibernateMappingContextConfiguration {

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

    }

And finally, refer in our application.yml the customized class we are going to use in our DataSource.

dataSource:
    dbCreate: update
    configClass: mypackage.GormConfiguration
like image 72
Wellington Souza Avatar answered Nov 06 '22 14:11

Wellington Souza


Not sure if the latest Grails 3 provides a more direct way of customizing the constraint names, but in Grails 2.4.5 and earlier versions the way to go is with a custom configuration subclass.

It essentially involves creating your own configuration by extending GrailsAnnotationConfiguration and overriding the secondPassCompile() method. In this method you can access your domain class and access/set many different properties including something like the foreign key constraint name.

For a detailed example please see Burt Beckwith's post: http://burtbeckwith.com/blog/?p=465

I believe the length limit of the name for a constraint is determined by the underlying database implementation and not GORM itself.

like image 24
wrj Avatar answered Nov 06 '22 15:11

wrj