《Hibernate学习笔记十一》:树状结构设计
这是马士兵老师讲解Hibernate的一个作业题,树状结构设计,这是一个比较典型的例子,因此有必要写篇博文记录下。
树状结构的设计,它是在同一个类中使用了多对一(ManyToOne)和一对多(OneToMany).
在完成这个题目我们应该按照如下的步骤进行:
1、先思考数据库的模型应该是什么样的??
数据库中的模型应该如下:即存在id p_id
2、思考面向对象的模型,及如何来进行映射???
根据数据库中表的特点,对象应该有id name;由于此类的对象与对象之间是多对一(即多个孩子对应一个父节点)和一对多(即一个父节点可以有多个孩子)的关系,因此就存在一个自己的引用(parent)以及孩子的Set集合(children);
3、思考如何进行增删改查???
实体类
注意里面的@OneToMany和@ManyToOne
@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(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") //即在数据库的表Org的外键名为parent_id
public Org getParent() {
return parent;
}
public void setParent(Org parent) {
this.parent = parent;
}
}
这样就完成了数状结构的设计,这个实体类中用到了OneToMany和ManyToOne.
考虑数据库的增删改查(CURD)操作
先看Save
@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 o11=new Org();
o11.setName("公司1下面的部门1");
Org o12=new Org();
o12.setName("公司1下面的部门2");
Org o21=new Org();
o21.setName("公司2下面的部门1");
Org o22=new Org();
o22.setName("公司2下面的部门2");
//建立双向关系
o.getChildren().add(o1);
o.getChildren().add(o2);
o1.getChildren().add(o11);
o1.getChildren().add(o12);
o2.getChildren().add(o22);
o2.getChildren().add(o21);
o1.setParent(o);
o2.setParent(o);
o11.setParent(o1);
o12.setParent(o1);
o21.setParent(o2);
o22.setParent(o2);
Session s=sessionFactory.getCurrentSession();
s.beginTransaction();
s.save(o);
s.getTransaction().commit();
}
测试结果如下:
再看Load,并打印输出这棵树
@Test
public void testLoad(){
testSave();
Session s=sessionFactory.getCurrentSession();
s.beginTransaction();
Org org=(Org)s.get(Org.class, 1);//由于我们在@OneToMany(fetch=FetchType.EAGER),因此,就可以一下子将孩子节点全部取出来
print(org,0);//输出
s.getTransaction().commit();
}
private void print(Org org,int level) {
String str="";
for(int i=0;i<level;i++){
str+="----";
}
System.out.println(str+org.getName());
for(Org o:org.getChildren()){
print(o,level+1);
}
}
打印输出的结果如下:
在load的过程中,我们在实体类中设置了@OneToMany(fetch=FetchType.EAGER),因此,就可以一下子将孩子节点全部取出来,如果不设置为EAGER,而是LAZY,则就是用到才会去取出来。
以上可以说是对OneToMany和ManyToOne的一个应用啦。
参考资料
1、马士兵《Hibernate学习视频》