Hi,
I've got a problem mapping a tree-like hierarchy consisting of objects of a single class Node:
Each Node has 0 or 1 parents and 0 or many children, i.e. a one-to-many relationship with other nodes via children and many-to-one via parents.
Code:
@Entity
@Table(name = "NODE")
public class Node
{
private Node parent;
private Set<Node> children();
// Getters and Setters omitted
}
Due to restrictions in the schema I'm using I have to map the relationships using a join table NODE_STRUCTURE, and I'd very much like the association to be bi-directional so that I can traverse the tree both ways in my code.
I've tried the following mapping:
Code:
@Entity
@Table(name = "NODE")
public class Node
{
@ManyToOne
@JoinTable(
name = "NODE_STRUCTURE",
joinColumns = {@JoinColumn(name = "CHILD_ID", referencedColumnName = "id", updatable = false)},
uniqueConstraints = {@UniqueConstraint(columnNames={"CHILD_ID","PARENT_ID"})},
inverseJoinColumns = @JoinColumn(name = "PARENT_ID", referencedColumnName = "id", updatable = false))
private Node parent;
@OneToMany(mappedBy="parent")
@Cascade(value = {org.hibernate.annotations.CascadeType.DELETE_ORPHAN,
org.hibernate.annotations.CascadeType.SAVE_UPDATE})
private Set<Node> children = new HashSet<Node>();
// Getters and Setters omitted
}
Which works except for the following case:
Step 1: Create two nodes 'node1' and 'node2' and save them - two inserts are executed, which is correct. At this point the two nodes are not related, which is also correct. So we have two rows in NODE and none in NODE_STRUCTURE.
Step 2: Add node1 as a child of node2 and save node1. What I'd expect would happen is an insert would be made on the NODE_STRUCTURE table, but What actually happens is an update, resulting in the relationship not being persisted. In cases where a Node already had a parent and we're changing the parentage of the node the update is sufficient, as there's already a row in NODE_STRUCTURE that the update can change.
I've also tried mapping the relationship as a many-to-many for both parent and children but this gives other problems which I can detail if anyone's interested.
My question is then:
Is this expected Hibernate behaviour, and if it is, how should I map a tree-like hierarchy on a single class with a join table?
Many thanks!
Brian