Search code examples
grailsgrails-orm

Unwanted GORM table creation


I have two domain classes, Person and Workshop. A Workshop has an owner of type Person, and many participants of type Person. A Person can be the participant of many workshops. When enrolling people in workshops I want to do so from the Workshop side like workshop.AddToParticipants() so here is how I set up my domain classes.

class Person {
    String name

    static hasMany = [enrolledWorkshops: Workshop]
    static belongsTo = [Workshop]

}

class Workshop {
    Date startDate
    Date endDate
    String name

    Person owner
    static hasMany = [participants: Person]
}

GORM correctly creates a WORKSHOP_PARTICIPANTS table with WORKSHOP_ID and PERSON_ID columns, and adds an OWNER_ID column to the WORKSHOP table. This is all good.

However, it ALSO creates a WORKSHOP_OWNER table with PERSON_ID and OWNER_ID columns! This makes no sense to me, and no matter how I try changing the GORM relationships I just can't get it to work how I want without this annoying extra table being created. How can I prevent the WORKSHOP_OWNER table from being created? Any help is greatly appreciated! (if it is of any help, I am using Grails 2.3.7)


Solution

  • In order to get rid of the WORKSHOP_OWNER table you'd have to replace Person owner with static belongsTo = [owner: Person] in the Workshop class. But that would conflict with static belongsTo = [Workshop] in the Person class. Both can't be owners.

    Try this:

    class Person {
        String name
    }
    
    class Workshop {
        Date startDate
        Date endDate
        String name
    
        static belongsTo = [owner: Person]
        static hasMany = [participants: Participant]
    }
    
    class Participant {
        person person
    
        static belongsTo = [workshop: Workshop]
    }
    

    In the above example, a Person owns a Workshop, and a Participant is owned by a Workshop. The workshop table will get a owner_id to refer to the person, which gets rid of the workshop_owner table.

    To add a Person to a Workshop you simply wrap it in a Participant

    workshop.addToParticipants(new Participant(person: somePerson))
    

    You'd loose the enrolledWorkshops property in Person, but you can accomplish the same thing with a query.

    def workshops = Workshop.withCriteria {
        participants {
            eq 'person', somePerson
        }
    }