Você está na página 1de 3

Recursive relation

Recursive relation
Recursive relations are possible. Typical example are Trees where each node can have a
subtree. We will create a Tree where each TreeItem knows its parent and its children. Full
source code is provided in the package: de.laliluna.relation.recursive
Classes

Tables

Annotation mapping.
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
....... snip ......
@Entity
public class TreeItem implements Serializable {
@ManyToOne
@JoinColumn(name="parent_id")
private TreeItem parent;
@OneToMany(mappedBy="parent", cascade = CascadeType.ALL)
private Set<TreeItem> children = new HashSet<TreeItem>();

The relation is in fact a simple one-to-many relation. @OneToMany(mappedBy="parent",


cascade = CascadeType.ALL) specifies that the relation is managed by the parent property.
@ManyToOne specifies the relation @JoinColumn(name="parent_id") specifies which
column is the foreign key column to the TreeItem primary key.
XML mapping.
<hibernate-mapping package="de.laliluna.example6">

<class name="TreeItem" table="ttreeitem" >


........ snip ......
<many-to-one name="parent" class="TreeItem" unique="true" notnull="false" >
<column name="parent_id" ></column>
</many-to-one>
<set name="children" inverse="true" cascade="all,delete-orphan">
<key column="parent_id"></key>
<one-to-many class="TreeItem" />
</set>
</class>
</hibernate-mapping>

What is interesting in the mapping is that I have set a cascade.


cascade="all,delete-orphan"

This is convenient in a twofold sense: First, when you create a tree, you only have to save the
top item. All other items will be saved automatically. Second, when you delete an item the
whole subtree will be deleted. The created table is:
CREATE TABLE ttreeitem
(
id int4 NOT NULL,
name varchar(255),
parent_id int4,
PRIMARY KEY (id),
FOREIGN KEY (parent_id)
REFERENCES ttreeitem (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
) ;

Samples of use:
/* create and set relationship */
TreeItem main = new TreeItem(null, "main");
TreeItem sub1 = new TreeItem(null, "go swimming");
sub1.setParent(main);
main.getChildren().add(sub1);
TreeItem sub11 = new TreeItem(null, "lake");
sub11.setParent(sub1);
sub1.getChildren().add(sub11);
session.save(main);
// cascade will save all the children
/* delete a sub tree */
// reattach subTree to the new session using lock
session.buildLockRequest(LockOptions.NONE).lock(sub1);
/* remove the children from the parent or it will be resaved
when the parent is saved.
*/
sub1.getParent().getChildren().remove(sub1);
session.delete(sub1);

Warning: You can create recursive relations with bag or set notation. If you want to use other
like an indexed list, you must create some dirty" work arounds. Have a look in the Hibernate
reference for more information.

Source: http://www.laliluna.de/jpa-hibernate-guide/ch07s08.html

Você também pode gostar