dev
dev

Reputation: 1085

How to set proper relation among two classes

I am having some issues with setting relation among two classes. I have 2 classes, Student:

class Student {
   String name
   Guardian father
   Guardian mother
   Guardian local_guardian
}

and Guardian:

class Guardian {
   String name;
   static hasMany = [children:Student]
   static mappedBy = [children:'father']
}

Here, I used mappedBy to map Guardian object to father property . Unless mappedBy, I was getting error telling, should use mappedBy with any of the 3 Student class property. I tried this query to enter some sample data

new Student(name:"John", father: new Guardian(name:"Michael").save(),
            mother: new Guardian(name:"Mary").save(),
            local_guardian: new Guardian(name:"James").save()).save(flush:true);

The data is getting saved successfully but my problem is, Since I used mappedBy with 'father' property, I am able to use Guardian.children only with that father object. when I try to get list of children with mother and local_guardian object, (eg: mother.children) getting null result. I tried by adding with addTo on the many side like

Guardian.findByName("Mary").addToChildren(
   Student.findByName("John")).save(flush:true);

and tried accessing

Guardian.findByName("Mary").children 

Here, I got the result , but it moved the child from father to mother object, and no longer able to access father.children How will I solve this scenario? What I am trying to achieve is, I should be able to get list of children from all 3 of the Guardian object . Here One Student object is pointing to 3 Guardian objects (father, mother, local_guardian) . So I should be able to get the list of children by

  1. father.children
  2. mother.children
  3. local_guard.children

How will I set the proper relation among these classes to solve my problem?

Upvotes: 0

Views: 77

Answers (2)

Sudhir N
Sudhir N

Reputation: 4096

If you want to implement this relation using hasMany then you will need to have three mappedBy in Guardian class.

static hasMany = [children:Student, motherChildres:Student, localGuardianChildrens:Student]
   static mappedBy = [children:'father', motherChildrens:'mother', localGuardianChildrens: 'local_guardian']

But this does not look good, instead you can implement a relation using a middle level domain class and add addToChildren and getChildrens methods in Guardian class like below.

class GuardianChildren {
   Guardian guardian
   Student student

   constraints {
     student unique: ['guardian']
   }

}

Guardian {
  void addToChildrens(Student child) {
      new GuardianChildren(guardian:this, student:child).save()
   }

   @Transient
   List<Student> getChildrens() {
      return  GuardianChildren.findAllByGuardian(this).children
  }
}

Student {

   @Transient
   Guardian getMother() {
     //find guardin children where guardian type is mother and children is this student
   }

  @Transient
  Guardian getFather() {..}
}

Remove hasMany from Guardian and father/mother properties from Student. You will also probably need a type field in Guardian to specify if this is mother/father etc

Upvotes: 1

Ted Delezene
Ted Delezene

Reputation: 2481

You likely want to use hasMany and belongsTo, then to define the guardian you might want to use something like a father, mother, localGuardian properties in the guardian object. With such a relationship you can then use transients to define the set of children and mother / father.

So for example

 class Student
     {
        String name
        Guardian local_guardian
        static belongsTo = [primaryGuardian: Guardian]
        static transients=['mother', 'father']
        //define the transients
        def getMother(){
            if(primaryGuardian.type == 'mother') {
               return primaryGuardian
           } else {
             return primaryGuardian.spouse
          }
        }
        //do something similiar for getFather
      }

     Class Guardian
        {
         String name
         String type
         Guardian spouse
         static hasMany = [children:Student, localGuardianStudents: Student]
        }    

Please note that this is just example code and may contain errors as I didn't test it.
So you can then create a guardian, and then add children by calling

guardian.addToChildren(child)

Anyways, this will let you get the children of a guardian by calling guardian.children, it lets you get the primary guardian (either the mother or father) of the child by calling child.primaryGuardian, and it lets you get the mother or father by calling child.mother without the need to add special types in there.

You will want to make sure that you modify the constraints here, so that the spouse could be null. Furthermore relationships of this nature can sometimes get tricky when creating them causing errors relating to missing ID numbers when you are trying to save, so you want to be sure that you make sure that both sides of the relationship are defined when you create and modify these objects.

Upvotes: 0

Related Questions