Showing posts with label create foreign key. Show all posts
Showing posts with label create foreign key. Show all posts

Monday, October 21, 2013

Grails GORM creating foreign key on runtime

GORM mappings let you configure pretty much anything you need in your Grails applications, but occasionally there are more obscure tweaks that aren’t directly supported, and in this case a custom Configuration class is often the solution.

By default Grails uses an instance of GrailsAnnotationConfiguration and the standard approach is to subclass that to retain its functionality and override the secondPassCompile() method.

Create this class (with an appropriate name and package for your application) in src/java or src/groovy:


package com.pritom

import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration
import org.hibernate.mapping.Column
import org.hibernate.mapping.ForeignKey
import org.hibernate.mapping.PersistentClass

/**
 * Created with IntelliJ IDEA.
 * User: pritom
 * Date: 21/10/13
 * Time: 10:41 AM
 * To change this template use File | Settings | File Templates.
 */
class GormConfiguration extends GrailsAnnotationConfiguration {
    boolean renamedForeignKeys = false

    @Override
    protected void secondPassCompile() {
        super.secondPassCompile()

        if (renamedForeignKeys) {
            return
        }

        renameForeignKeys()
        renamedForeignKeys = true
    }

    void renameForeignKeys() {
        classes.values().each { PersistentClass persistentClass ->
            /**
             * There must be a domain name 'SportUser' which has a field 'user_id'.
             */
            if(persistentClass.entityName.equalsIgnoreCase("com.pritom.SportUser")) {
                persistentClass.table.columns.each {
                    /**
                     * user_id: Column name to behave as a foreign key
                     * There must be a domain name 'User' to linked with it.
                     */
                    if(it.value.name.equalsIgnoreCase("user_id")) {
                        Column column = (Column) it.value;
                        /**
                         * ACL_USER: Foreign key constraints name
                         * com.pritom.User: Domain to make the foreign object
                         */
                        persistentClass.table.createForeignKey("ACL_USER", [column], "com.pritom.User")
                    }
                }
            }
        }
    }

    String createHumanReadableName(ForeignKey key) {
        "${key.columns.first().name}__${key.referencedTable.name}_fkey"
    }
}


What is left is to activate the code which is a one liner, we just have to add a configClass parameter to the datasource configuration:

    dataSource {
        configClass = com.pritom.GormConfiguration
        driverClassName = "com.mysql.jdbc.Driver"
        dbCreate = "create"
        url = "jdbc:mysql://localhost/grails_db"
        username = "grails"
        password = "grails"
    }