inheritance in Grails domain model

grails, grails-orm

Solution

Solved!

Add the class below to `src/java` (this class cannot be written in Groovy)

package org.example;

import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration;
import org.hibernate.MappingException;
import org.hibernate.mapping.JoinedSubclass;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.RootClass;

import java.util.Iterator;

public class TablePerSubclassConfiguration extends GrailsAnnotationConfiguration {

    private static final long serialVersionUID = 1;

    private boolean alreadyProcessed = false;

    @Override
    protected void secondPassCompile() throws MappingException {
        super.secondPassCompile();

        if (alreadyProcessed) {
            return;
        }

        for (PersistentClass persistentClass : classes.values()) {
            if (persistentClass instanceof RootClass) {
                RootClass rootClass = (RootClass) persistentClass;

                if (rootClass.hasSubclasses()) {
                    Iterator subclasses = rootClass.getSubclassIterator();

                    while (subclasses.hasNext()) {

                        Object subclass = subclasses.next();

                        // This test ensures that foreign keys will only be created for subclasses that are
                        // mapped using "table per subclass"
                        if (subclass instanceof JoinedSubclass) {
                            JoinedSubclass joinedSubclass = (JoinedSubclass) subclass;
                            joinedSubclass.createForeignKey();
                        }
                    }
                }
            }
        }

        alreadyProcessed = true;
    }
}

Then in `DataSource.groovy` set this as the configuration class

dataSource {
    configClass = 'org.example.TablePerSubclassConfiguration'
    pooled = true
    driverClassName = "org.h2.Driver"
    username = "sa"
    password = ""
    dbCreate = "update"
    url = "jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
}

I've submitted a pull request to Grails that fixes this. The fix was be included in Grails 2.3.9.

Problem

My Grails app's domain model has the following requirements: - a user belong to zero or one organisations - an organisation is either a charity or a company - charities and companies have some some common fields and also some (non-nullable) fields that are unique to each organisation type I put the common organisation fields into an abstract `Organisation` class which `Charity` and `Company` both extend. I can't store this hierarchy in a single table because there are non-nullable fields that are specific to each organisation type. The relevant parts of the domain model are shown below: ``` class User { String name static belongsTo = [organization: Organization] static constraints = { organization nullable: true } } abstract class Organization { String name static hasMany = [users: User] static mapping = { tablePerHierarchy false } } class Charity extends Organization { // charity-specific fields go here } class Company extends Organization { // company-specific fields go here } ``` When I look at the MySQL schema generated from this model, the inheritance relationship between organisation-company and organisation-charity seems to have been completely ignored. Although there is an organisation table with a name column, it has no primary-foreign key relationship with either company or charity

Original source