Search code examples
hibernategrailsnaming-conventionsgrails-ormnaming

GORM: automatically prefix each table name with the domain class namespace


I have separated all my domain classes into namespaces and I would like GORM to keep this separation at the DB level, using table prefixes.

For example:

auth.User  -> auth__user
auth.Group -> auth__group
auth.Role  -> auth__role
cms.Page   -> cms__page
cms.Post   -> cms__post
cms.Image  -> cms__image

I'm looking for a way to do that without having to write the table names inside each domain class.

I've gotten Hibernate to recognize a custom NamingStrategy, but alas the string I get passed to classToTableName() is only the short class name; the namespace is nowhere to be seen.

Is there a way to write a NamingStrategy that knows what the class namespace is? (possibly not)

Is there some other automagic Grails thing I could try? Maybe some code that could be written once and applied to all domain classes?

I see that Grails has a grails.gorm.table.prefix.enabled settings for plugins, that somehows manages to prefix the plugin name to the tables. Can I use the same technique to add my namespaces? I looked in the sources, but I couldn't find the place where grails.gorm.table.prefix.enabled is read and applied.


Solution

  • You can achieve your requirement by using custom NamingStrategy.

    For that you have put following line in DataSource.groovy

    hibernate {
        ...
        naming_strategy = com.test.CustomNamingStrategy
    }
    

    And you have to extend ImprovedNamingStrategy

    package com.test
    
    import grails.util.Holders
    import org.hibernate.cfg.ImprovedNamingStrategy
    
    /**
     * Created by ramsharan on 9/11/14.
     */
    class CustomNamingStrategy extends ImprovedNamingStrategy {
        String classToTableName(String className){
            Class clazz = Holders.grailsApplication.domainClasses.find { it.clazz.simpleName == className }.clazz
            String packageName = clazz.getPackage().getName()
            "${packageName}__${className.toLowerCase()}"
        }
    }
    

    I have used following two links as references :

    For Custom Naming Strategy

    For getting package name from class name