树状结构的设计(把一棵树存入数据库的hibernate映射,及数据库表的设计)

来源:互联网 发布:管家婆数据备份与恢复 编辑:程序博客网 时间:2024/05/22 03:13

数据库模型(id-pid):一个父亲有多个孩子,而一个孩子只有一个父亲,这样的结构就是一颗树。在数据库表中,设计的是idpidparent_id)。通过idpid就存放一颗树了。

从面向对象的设计角度出发,在树的节点类中不宜放pid,一个节点有1个或者0个父亲,而有0个或者孩子。因此设计如下:这是一个组织机构,每个机构有父机构和子机构。

package com.xie.hibernate.modal;

 

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> childrenOrgs=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> getChildrenOrgs() {

    return childrenOrgs;

}

public void setChildrenOrgs(Set<Org> childrenOrgs) {

    this.childrenOrgs = childrenOrgs;

}

@ManyToOne

@JoinColumn(name="p_id")

public Org getParent() {

    return parent;

}

public void setParent(Org parent) {

    this.parent = parent;

} 

}

下面是junit的测试方法:

//生成数据库表,同时插入数据:

    @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 o3=new Org();

       o3.setName("分公司1的分公司1");

       Org o4=new Org();   

       o4.setName("分公司1的分公司2");

       Org o5=new Org();   

       o5.setName("分公司2的分公司1");

       Org o6=new Org();   

       o6.setName("分公司1的分公司1分公司1");

      

       o1.setParent(o);

       o2.setParent(o);

       o3.setParent(o1);

       o4.setParent(o1);

       o5.setParent(o2);

       o6.setParent(o3);

       o.getChildrenOrgs().add(o1);

       o.getChildrenOrgs().add(o2);

       o1.getChildrenOrgs().add(o3);

       o1.getChildrenOrgs().add(o4);

       o2.getChildrenOrgs().add(o5);

       o3.getChildrenOrgs().add(o6);

       try {

           Session session=sf.getCurrentSession();

           session.beginTransaction();

            //注解中加了cascade={CascadeType.ALL},只存跟节点就把整颗树

            //存到了数据库。

           session.save(o);

           session.getTransaction().commit();

       } catch (Exception e) {

           e.printStackTrace();

       }

 

      

    }

   //load一棵树到内存,由于有fetch=FetchType.EAGEROrg(Org) //session.load(Org.class, 1);将树中的所以节点load到了内存,同时维护着

   //父子节点的关系。

    @Test

    public void testLoad(){

       testSave();

       try {

           Session session=sf.getCurrentSession();

           session.beginTransaction();

           Org o=(Org) session.load(Org.class, 1);

           Print(o,0);

           session.getTransaction().commit();

       } catch (Exception e) {

           e.printStackTrace();

       }

    }

/*

 * 递归打印出一颗树。

 */

    private void Print(Org o,int level) {

       String preLevel="";

       for (int i = 0; i < level; i++) {

           preLevel+="----";

       }

       System.out.println(preLevel+o.getName());

       for (Org org:o.getChildrenOrgs()) {

           Print(org,level+1);

       }

    }

}

输出结果:

总公司

----分公司1

--------分公司1的分公司1

------------分公司1的分公司1分公司1

--------分公司1的分公司2

----分公司2

--------分公司2的分公司1