树状结构的数据库存储,一般是放在一张表里面,存一个自己的id,一个父节点parend_id,然后是其他属性,如下图所示:
对于这种结构,hibernate采用面向对象的处理方式,每个节点都有父节点,可能有多个孩子节点。以组织org树状结构为例: Org.java
package com.hibernate.demo.model; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; @Entity public class Org { private int id; private String name; private Set<Org> children = new HashSet<Org>(); private Org parent ; @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @OneToMany(mappedBy="parent", cascade=CascadeType.ALL, fetch=FetchType.EAGER) public Set<Org> getChildren() { return children; } public void setChildren(Set<Org> children) { this.children = children; } @ManyToOne @JoinColumn(name="parent_id") public Org getParent() { return parent; } public void setParent(Org parent) { this.parent = parent; } }
以上结构中,注意映射关系,还有cascade、fetch两个标注。下面使用junit4来写存储测试:
@Test public void testSave(){ Org o = new Org(); o.setName("总公司"); Org o1 = new Org(); o1.setName("分公司1"); Org o2 = new Org(); o2.setName("分公司2"); Org o21 = new Org(); o21.setName("分公司2-1"); o.getChildren().add(o1); o.getChildren().add(o2); o2.getChildren().add(o21); o21.setParent(o2); o2.setParent(o); o1.setParent(o); Session s = sf.getCurrentSession(); s.beginTransaction(); s.save(o); s.getTransaction().commit(); }
下面使用junit4来写读取并打印测试:
@Test public void testLoad(){ Session s = sf.getCurrentSession(); s.beginTransaction(); Org o = (Org)s.load(Org.class, 3); print(o, 0); s.getTransaction().commit(); } private void print(Org o, int level) { // TODO Auto-generated method stub StringBuffer strPre = new StringBuffer(); for(int i=0; i<level; i++){ strPre.append("----"); } System.out.println(strPre.toString() + o.getName()); for(Org child : o.getChildren()){ print(child, level + 1); } }
此处,如果fetch设置为贪婪eager模式,第一次打印时就把所有节点取出来了;如果fetch设置为懒做lazy模式,则在递归过程中去取数据,这适用于ajax取子节点的情况。
取自尚学堂--马士兵老师hibernate视频教程。