Dear all
I would like to implement the "Nested Set Model" using hibernate.
The Nested step model has the advantage that it nicely allows us to map tree like
strutures to the database. Some nice articles one the subject, are available at:
http://www.sitepoint.com/print/hierarch ... a-database
http://www.edutech.ch/contribution/nstrees/index.php
http://threebit.net/tutorials/nestedset/tutorial1.html
http://www.intelligententerprise.com/00 ... stid=60290
Does someone has implemented this? I an trying to find how to translate this to
hibernate in the best way.
So I see the following steps to create the nested set:
1 - Create a NestedSet.java class.
2 - Create the hibernate mapping file.
3 - Create a NestedSetInterceptor, ??? ! Not sure if this is need.
4 - Implement a NestedSetDao object.
For the step 1 I create the following class;
public class NestedSet {
public NestedSet() {
super();
}
public NestedSet(NestedSet parent) {
this.parent = parent;
}
// primary key
private long id;
// fields
private long left;
private long right;
private NestedSet parent = null;
private List children = new ArrayList();
public List getChildren() {
return children;
}
public void setChildren(List children) {
this.children = children;
}
public NestedSet getParent() {
return parent;
}
public void setParent(NestedSet parent) {
this.parent = parent;
}
public void addChild( NestedSet child) {
if (child == null) {
throw new IllegalArgumentException("Null child");
}
if (child.getParent() != null ) {
child.getParent().getChildren().remove(child);
}
child.setParent(this);
children.add(child);
}
/**
* How Many Descendants, each descendant increments the right value of the node with 2,
* @return How many descendants
*/
public long getDescendantsCount() {
return (right - left - 1) / 2;
}
}
2- For the mapping is were the questions arise.The NestedSet.java is a self
reference parent child relation that can not be implemented using the standard
many-to-one/one-to-many mapping pair. Because the parent child relations are
created by the LFT and RGT table colunns.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping SYSTEM
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
<hibernate-mapping package="org.hibernate.auction.model">
<class name="NestedSet" table="NESTED_SET">
<id
column="ID"
name="id"
type="long"
unsaved-value="0"
access="field"
>
<generator class="native" />
</id>
<property
name="left"
column="LFT"
not-null="true"
type="long"
access="field"
/>
<property
name="right"
column="RGT"
not-null="true"
type="long"
access="field"
/>
<query name="retrive.node.subtree"><![CDATA[
from NestedSet as node
where node.left >= ? and cat.right <= ?
ORDER BY node.left ASC;
]]>
</query>
<query name="retrive.node.parent"><![CDATA[
from NestedSet as node
where node.left <= ?
]]>
</query>
<sql-query name="open.space.rigth"><![CDATA[
UPDATE NESTED_SET SET rgt=rgt+2 WHERE rgt>?;
]]>
</sql-query>
<sql-query name="open.space.left"><![CDATA[
UPDATE NESTED_SET SET lft=lft+2 WHERE lft>?;
]]>
</sql-query>
<sql-query name="close.space.rigth"><![CDATA[
UPDATE NESTED_SET SET rgt=rgt-2 WHERE rgt>?;
]]>
</sql-query>
<sql-query name="close.space.left"><![CDATA[
UPDATE NESTED_SET SET lft=lft-2 WHERE lft>?;
]]>
</sql-query>
</class>
</hibernate-mapping>
So I have not found a proper way of mapping the parent and children properties,
in the hibernate mapping file. When we load a NestedSet from the database it should
have is parent property set to his parent and the children property set to the list
of his children. The only way that I see how this can be done is using an
Interceptor.
By using an Interceptor I was thinking in the onLoad method execute 2 queries, the
retrive.node.subtree to obtain the children and the the retrive.node.parent to
retrive the parent but by using queries I will not be using the cache?
To insertion of nodes in the tree I was planning on using the
open.space(left/rigth) sql-query followed by the insert statement.
To removal of nodes in the tree I was planning on using the close.space(left/rigth)
sql-query followed by the remove sql.
Please help me!
Regards Oscar