views:

24

answers:

1

Hello,
I'm not sure whether it is the right terminology for this kind of relationship, so please correct me. I need to define a domain class, which maps to a table in the database. The class needs to define a hierarchy of relationships of the same type. For eg, say I need to model the below roles with the same class Admin > Manager > Supervisor > associate .. etc.

class RoleType {
    String roleName
    String description

    static hasMany = [parentType: RoleType]
}

so, through the parenttype, I may be able to define the hierarchy. Note that it is not inheritance. I may also define 1:m relationship towards the immediate child aswell. Now, how easily I can find the contained objects. For eg, if I need to find all the roles below Manager (say, Supervisor, Associate), or under supervisor (associate) etc. I use Grails.

thanks.

+1  A: 

Defining the relationship

What you're defining is a unidirectional one-to-many, with the parent being the 'owner' of the relationship. If you define it like this:

class RoleType {
    String roleName
    String description
    static hasMany = [children: RoleType]
}

Then you can do something like this:

def superManager = new RoleType(roleName: 'SuperManager')
def manager = new RoleType(roleName: 'Manager')

superManager.addToChildren(manager);

Or I believe you can shorthand the same thing like this:

def superManager = new RoleType(roleName: 'SuperManager').addToChildren(roleName: 'Manager').save()

By defining the relationship with [children: RoleType], Grails creates a collection on the domain called children that you can access like any other property, e.g. myRole.children.each { it.doSomething() }.

To make it easier to work with, you could also make the relationship bidirectional by adding the following property:

RoleType parent

If you use the dynamic addTo* methods, they should ensure that both ends of the relationship get their properties correctly set. Have a look at this for additional reference.

Retrieving all descendants

You have a few options here, but I don't think there's a way built into GORM to do it automatically.

One option would be to write your own recursive or iterative method that grabs and collects all of the children. An example of this can be found here.

Alternatively, if you execute this method a lot and it become a bottleneck, you could do some manual manipulation of your database. You might have triggers that operate on inserts and updates in your RoleType table that maintain lists of implicit relationships between all RoleTypes.

For example, if you create a RoleType A -> RoleType B -> RoleType C relationship, the triggers might create (in a separate table) a RoleType A -> RoleType B, RoleType A -> RoleType C, and RoleType B -> RoleType C relationship. You could then query this table by a single parent and get all of its implied children/descendants. I've seen this done for complex ACL processing.

Rob Hruska
Rob .. thank you for the detailed answer.. I know how to recurse through a tree in groovy, still wish an easy way in gorm.. I'll mark the question answered, if no one comment on it. thanks...
bsreekanth
@bsreekanth - I'm not aware of an out-of-the-box way to do the query with gorm; there's probably a way you could do it by manually constructing an HQL query.
Rob Hruska
Rob.. thanks again for your research, and additional details.. learned new ways to do things.. thanks
bsreekanth