作业-树状结构设计
作業:樹狀結構的設計
在同一個類中使用OneToMany和ManyToOne
首先想數據庫的模型,再想面向對象的模型,然后再來想怎么去做映射,做完映射在想怎么去做CRUD。
1.首先設計數據庫的模型
應該是Id、parent_Id.單一父親,好多孩子這就是一棵樹。
數據庫首先存在的屬性有:
Id<int> parent_Id<int> name<String>
例子:
ID ? Parent_ID ? 公司
1 ? ? ? null ? ? 分公司1
2 ? ? ? 1 ? ? ? ?分公司2
3 ? ? ? 2 ? ? ? ?分公司2_1
實體類:
@joinColumn(name = "parent_id") public Org getParent() { return parent; } public void setParent(Org parent) { this.parent = parent; } }
如何來理解這張表,我們假設有三張表(都是id、name)。
A、B、C假設B的父親是A,B的孩子是C,B通過parent_id去參考父親A的ID,
C通過parent_id去找父親B。只不過是多張表合成一張表。然后每一個人
的parent_id都去參考另外一條記錄了,也就是參考自身這張表。是
一對多和多對一的雙向關聯關系。
測試,輸出的建表sql語句:
alter table Org?
? ? ? ? drop?
? ? ? ? foreign key FK136C4424F8DF5
? ? drop table if exists Org
? ? create table Org (
? ? ? ? id integer not null auto_increment,
? ? ? ? name varchar(255),
? ? ? ? parent_id integer,
? ? ? ? primary key (id)
? ? )
? ? alter table Org?
? ? ? ? add index FK136C4424F8DF5 (parent_id),?
? ? ? ? add constraint FK136C4424F8DF5?
? ? ? ? foreign key (parent_id)?
? ? ? ? references Org (id)
添加測試:
@Test public void testTreeAdd(){ 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"); o.getChildren().add(o1); o.getChildren().add(o2); o.getChildren().add(o11); o.getChildren().add(o12); o11.setParent(o1); o12.setParent(o1); o1.setParent(o); o2.setParent(o); //可以先存父親,再存孩子,也可以讓Org的Childern設置CascadeType.ALL //這里用的是設置CascadeType.ALL,所以只存父親就可以了 sessionFactory=new AnnotationConfiguration().configure().buildSessionFactory(); Session session=sessionFactory.openSession(); session.beginTransaction(); session.save(o); session.getTransaction().commit(); session.close(); }輸出的sql語句:
Hibernate:?
? ? insert?
? ? into
? ? ? ? Org
? ? ? ? (name, parent_id)?
? ? values
? ? ? ? (?, ?)
Hibernate:?
? ? insert?
? ? into
? ? ? ? Org
? ? ? ? (name, parent_id)?
? ? values
? ? ? ? (?, ?)
Hibernate:?
? ? insert?
? ? into
? ? ? ? Org
? ? ? ? (name, parent_id)?
? ? values
? ? ? ? (?, ?)
Hibernate:?
? ? insert?
? ? into
? ? ? ? Org
? ? ? ? (name, parent_id)?
? ? values
? ? ? ? (?, ?)
Hibernate:?
? ? insert?
? ? into
? ? ? ? Org
? ? ? ? (name, parent_id)?
? ? values
? ? ? ? (?, ?)
Hibernate:?
? ? update
? ? ? ? Org?
? ? set
? ? ? ? name=?,
? ? ? ? parent_id=??
? ? where
? ? ? ? id=?
Hibernate:?
? ? update
? ? ? ? Org?
? ? set
? ? ? ? name=?,
? ? ? ? parent_id=??
? ? where
? ? ? ? id=?
結果:
id ? ?name ? ? ? ? ? ?parent_id
1 ? ? 總公司 ? ? ? ? ? null
2 ? ? 分公司1下公司1 ? 5
3 ? ? 分公司1下公司2 ? 5 ? ? ?
4 ? ? 分公司2 ? ? ? ? ? 1
5 ? ? 分公司1 ? ? ? ? ? 1
讀取測試(用遞歸):
簡單的方式就是Org的Childern設置fetch=FetchType.EAGER,最好的方式是遞歸。
?
?
首先用fetch=FetchType.EAGER測試:
@Test public void testTreeLoad(){ sessionFactory=new AnnotationConfiguration().configure().buildSessionFactory(); Session session=sessionFactory.openSession(); session.beginTransaction(); Org o =(Org) session.load(Org.class,1); Treeprint(o); session.getTransaction().commit(); session.close(); } private void Treeprint(Org o) { System.out.println(o.getName()); for(Org child:o.getChildren()){ Treeprint(child); } }測試結果:
Hibernate:?
? ? select
? ? ? ? org0_.id as id0_1_,
? ? ? ? org0_.name as name0_1_,
? ? ? ? org0_.parent_id as parent3_0_1_,
? ? ? ? children1_.parent_id as parent3_0_3_,
? ? ? ? children1_.id as id3_,
? ? ? ? children1_.id as id0_0_,
? ? ? ? children1_.name as name0_0_,
? ? ? ? children1_.parent_id as parent3_0_0_?
? ? from
? ? ? ? Org org0_?
? ? left outer join
? ? ? ? Org children1_?
? ? ? ? ? ? on org0_.id=children1_.parent_id?
? ? where
? ? ? ? org0_.id=?
Hibernate:?
? ? select
? ? ? ? children0_.parent_id as parent3_0_1_,
? ? ? ? children0_.id as id1_,
? ? ? ? children0_.id as id0_0_,
? ? ? ? children0_.name as name0_0_,
? ? ? ? children0_.parent_id as parent3_0_0_?
? ? from
? ? ? ? Org children0_?
? ? where
? ? ? ? children0_.parent_id=?
Hibernate:?
? ? select
? ? ? ? children0_.parent_id as parent3_0_1_,
? ? ? ? children0_.id as id1_,
? ? ? ? children0_.id as id0_0_,
? ? ? ? children0_.name as name0_0_,
? ? ? ? children0_.parent_id as parent3_0_0_?
? ? from
? ? ? ? Org children0_?
? ? where
? ? ? ? children0_.parent_id=?
Hibernate:?
? ? select
? ? ? ? children0_.parent_id as parent3_0_1_,
? ? ? ? children0_.id as id1_,
? ? ? ? children0_.id as id0_0_,
? ? ? ? children0_.name as name0_0_,
? ? ? ? children0_.parent_id as parent3_0_0_?
? ? from
? ? ? ? Org children0_?
? ? where
? ? ? ? children0_.parent_id=?
Hibernate:?
? ? select
? ? ? ? children0_.parent_id as parent3_0_1_,
? ? ? ? children0_.id as id1_,
? ? ? ? children0_.id as id0_0_,
? ? ? ? children0_.name as name0_0_,
? ? ? ? children0_.parent_id as parent3_0_0_?
? ? from
? ? ? ? Org children0_?
? ? where
? ? ? ? children0_.parent_id=?
總公司
分公司1
分公司1下公司2
分公司1下公司1
分公司2
如何展現成樹狀?
?
@Test public void testTreeLoad(){ sessionFactory=new AnnotationConfiguration().configure().buildSessionFactory(); Session session=sessionFactory.openSession(); session.beginTransaction(); Org o =(Org) session.load(Org.class,1); Treeprint(o,0); session.getTransaction().commit(); session.close(); } private void Treeprint(Org o,int level) { //level是構建樹狀前的縮進 String preStr=""; for(int i=0;i<level;i++){ preStr+="----"; } System.out.println(preStr+o.getName()); for(Org child:o.getChildren()){ Treeprint(child,level+1); } }測試結果:
總公司
----分公司2
----分公司1
--------分公司1下公司2
--------分公司1下公司1
如果這棵樹非常大我們用EAGER就不合適了,需要把它去掉了,什么時候需要(get)才從DB拿出。
也就是使用LAZY的方式,什么時候需要的時候才發送QL 從DB中獲取
?
總結
- 上一篇: parasoft Jtest 使用教程:
- 下一篇: Less相关