Nested set plugin for Grails

What is Nested set?

A nested set model is a way of organising hierarchical data in a relational database, see Wikipedia.

Installation instructions

Download the grails-nested-set-0.3.zip and run

1 grails install-plugin /path/to/the/plugin.zip

Essentials

The NestedSet plugin injects the functionality of a nested set to any domain class. It is as simple as declaring a static variable.

1 class Employee {
2     String firstName
3     String lastName
4 
5     static nestedSet = true
6 }

Moreover, it does not interfere with the domain at all. The whole structure is stored in a domain class named NestedSet, in a separate table.

It is possible to create a Nested set from any of your domain classes. Nevertheless, the tree structures can contain only classes with common ancestor. This ancestor have to be marked as a nested set.

The following example will create 2 tree structures: Employee and Location.

 1 class Employee {
 2     String firstName
 3     String lastName
 4 
 5     static nestedSet = true
 6 }
 7 
 8 class Location{
 9     String name
10     static nestedSet = true
11 }
12 
13 class Continent extends Location{}
14 
15 class State extends Location{}
16 
17 class City extends Location{}

The Location tree structure can contain any of the descendants - Continent, State, City.

The methods of the NestedSet are described in the following example.

Example

 1 class Employee {
 2     String firstName
 3     String lastName
 4 
 5     static nestedSet = true
 6 
 7     /** 
 8     *    Returns the direct manager of the employee
 9     **/
10     def manager() {
11         nestedSetGetParent()
12     }
13 
14     /**
15     *    Returns all managers of the employee
16     **/
17     def managers() {
18         nestedSetGetAncestors()
19     }
20 
21     /**
22     *    Returns direct subordinates of the employee
23     **/
24     def directSubordinates() {
25         nestedSetGetChildren()
26     }
27 
28     /**
29     *    Returns direct subordinates of the employee and their subordinates
30     **/
31     def allSubordinates() {
32         nestedSetGetDescendants()
33     }
34 
35     /**
36     *    Returns the top managers (having no manager)
37     **/
38     static def topManagers() {
39         nestedSetGetRoots()
40     }
41 
42     /**
43     *    Promote employee to be the top manager
44     **/
45     def makeTopManager() {
46         nestedSetMakeRoot()
47     }
48 
49     /**
50     *    Remove the employee and all subordinates from hierarchy
51     **/
52     def outsourceDepartment() {
53         nestedSetRemove()
54     }
55 
56     /**
57     *    Adds a new subordinate
58     **/
59     def addSubordinate(so) {
60         nestedSetAddChild(so)
61     }
62 
63     /**
64     *    Move the whole department under different manager
65     **/
66     def reorganize(newManager){
67         nestedSetMoveTo(newManager)
68     }
69 
70     String toString() {
71         "$firstName $lastName" 
72     }
73 }
74 }

Limitations

  • If DB set to update, it does not create the appropriate indexes.... Human:Hibernate 0:1
  • It works well for "slowly changing" (static) hierarchical structures. The dynamic ones should be stored using different structure.

grails-nested-set-0.1.zip - Nested set plugin (5.5 KB) Roman Mackovčák, 03/15/2010 12:10 pm

grails-nested-set-0.2.zip - Nested set plugin (6 KB) Petr Mourek, 06/18/2010 12:59 pm

grails-nested-set-0.3.zip - Nested set plugin (6.1 KB) Petr Mourek, 07/28/2010 02:39 pm

Also available in: HTML TXT