Grail Domain Inheritance

The domain model of my Grails application has the following requirements:

  • the user belongs to zero or one organization.
  • the organization is either a charitable organization or a company
  • charitable organizations and companies have some common fields, as well as some (non-zero) fields that are unique to each type of organization.

I put the general fields of the organization into an abstract Organisationclass that extends Charityand Company. I cannot save this hierarchy in one table because there are fields with invalid values ​​that apply to each type of organization. Below are the relevant parts of the domain model:

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
}

MySQL, , - -, , . , , -

+4
3

!

src/java ( 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;
    }
}

DataSource.groovy

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"
}

Grails, . Grails 2.3.9.

+1
  • , IanRoberts MySQL H2. : , organization_id FK users.
  • " " (tablePerHierarchy false), - . Charity Company , PK Organization. , GORM/Hibernate3, , . .
+2

ORM RDBS.

  • tablePerHierarchy false

So, you have three tables: organization, charity, company. The user belongs only to the Organization (not Charity or Company). How are you going to get the value of certain fields? There is a USER. We know the ORGANIZATION, but we don’t know the Charity or Company. I think you understand ...

I can offer you three solutions:

1. tablePerHierarchy true (But you need to have fields with null values ​​\ Company fields)

2.

class User {
    static belongsTo = [charity: Charity, company: Company]
}


class Charity {
    String name
    static hasMany = [users: User]
    // charity-specific fields go here
}

class Company {
    String name
    static hasMany = [users: User]
    // company-specific fields go here
}  

3.

class User {
    static belongsTo = [organization: Organization]
}

class Organization {    
    String name
    Charity charity //nullable
    Company company //nullable
    static hasMany = [users: User]
}

class Charity {
    static belongsTo = [organization: Organization]
    // charity-specific fields go here
}

class Company {
    static belongsTo = [organization: Organization]
    // company-specific fields go here
}  
+1
source

Source: https://habr.com/ru/post/1524746/


All Articles