hibernate之树状映射结构
来源:互联网 发布:牛轧糖哪个牌子好淘宝 编辑:程序博客网 时间:2024/06/07 15:09
原文地址:http://www.2cto.com/kf/201410/340717.html
提到树状映射,许多人肯定会头疼死了,因为看树状这俩字就肯定想到会跟数据结构打交道,而数据结构是本科阶段最重要也是最难学的一门专业课。说实话摩罗我《数据结构》这门课学得也不咋滴,花了点时间终于完成了hibernate之树状映射这个小程序。
首先我先定义了个公司组织类(Org),一个组织下面可以有多个子组织,但每个组织都只有一个上级组织,也就是传说中的一对多的关系,但这个关系是双向的。提到双向关系,我们第一件事就是在双向关系的两边都要设双向关联,另外为了防止产生冗余,我们要在其中的一方设mappedBy,至于设在哪方,等下在下面的程序中解释。
既然确定了这个组织类(Org)是双向关系的,那么该如何定义这个类呢?首先从数据库表设计的角度来考虑一下,每个组织下面都可能有多个子组织,而每个子组织对应的只有一个上级组织,这是典型的一对多关系,一个组织拥有它自己的id以及组织名字(name),这俩已经可以描述这个组织了,但怎么描述各个组织之间的关系呢?也就是说在表里我们还必须定义字段去提现关系。因为是一对多的关系,一对多映射关系有一个规律很重要,那就是必须是在“多”的这方设置“一”的这方的外键,在这里就是在下级组织中设置上级组织的外键,这样通过这个外键我们就可以找到这个组织对应的上级组织是谁。有的同学可能会疑惑了:为什么非要在“多”的这方设置设置“一”的这方的外键呢?而不是反过来呢?来看看下面这个例子就会明白为什么要这样设置了。
注:以下是数据库表里的错误设计方法:
GroupId
GroupName
UserId
1
Group_1
1
1
Group_1
2
UserId
UserName
1
moluo
2
xingzhe
一个组(Group)里可以有多个用户(User),这是典型的一对多关系,如果在Group(也就是在“一”的这方)设置User(“多“的这方)的外键,那么表中红色字体部分的信息是不是产生了冗余?这只产生了两条记录的冗余,还可以接受。但如果Group表有很多个字段,并且有很多条记录呢?这样设计产生的冗余就大得夸张了,所以必须在“多”的这方设置“一”的这方的外键。
解释完数据库里表的设计方法,再来讲讲程序里Org这个类该如何定义。
首先Org这个类是一个组织,从面向对象的角度来考虑,它既有上级组织,也有下级组织,当然id和name这俩属性是必不可少的。另外更重要的是它的上级组织以及下级组织实际上也是一个组织,于是我就定义出了下面这个Org类:
package
com.hibernate.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;
import
javax.persistence.Table;
@Entity
@Table
(name=_Organization)
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;
}
}
</org></org></org></org>
再来解释一下cascade,该属性定义的是类与类之间的级联关系,定义的级联关系将被容器视为将当前类对象以及与之关联的类对象采取相同的操作,而且这种级联关系是递归的。cascade属性值有:ALL:表示所有情况都进行相同操作,即save、update、delete;PERSIST:这个表示在保存时采取相同的操作,MERGE是JPA的官方叫法,实际上就跟sava()一样;REMOVE:这个表示级联删除,实际上跟delete()方法一样;REFRESH:级联刷新。
接着解释一下fetch:fetch是读操作,它有俩属性,LAZY:表示只读取当前对象,关联对象不读;EAGER:当前对象被读取的时候,关联对象也会被读取,而且这种级联关系是递归的。
@OneToMany:表示当前这个类对象(实体)对应getXXX()方法表示的属性XXX对应的对象(实体)是一对多的关系。
@ManyToOne:表示当前这个类对象(实体)对应getXXX()方法表示的属性XXX对应的对象(实体)是多对一的关系。
@JoinColumn:用来注释表中的字段名字。
最后再来看看JUnit Test Case:
package
com.hibernate.model;
import
org.hibernate.Session;
import
org.hibernate.SessionFactory;
import
org.hibernate.cfg.AnnotationConfiguration;
import
org.hibernate.tool.hbm2ddl.SchemaExport;
import
org.junit.AfterClass;
import
org.junit.BeforeClass;
import
org.junit.Test;
public
class
TreeTest {
public
static
SessionFactory sf =
null
;
@BeforeClass
public
static
void
beforeClass(){
try
{
sf =
new
AnnotationConfiguration().configure().buildSessionFactory();
}
catch
(Exception e) {
e.printStackTrace();
}
finally
{
}
}
@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
);
o.getChildren().add(o1);
o.getChildren().add(o2);
o1.getChildren().add(o11);
o1.getChildren().add(o12);
o12.getChildren().add(o21);
o1.setParent(o);
o2.setParent(o);
o11.setParent(o1);
o12.setParent(o1);
o21.setParent(o2);
Session session = sf.getCurrentSession();
session.beginTransaction();
session.save(o);
session.getTransaction().commit();
}
@Test
public
void
testLoad() {
testSave();
Session session = sf.getCurrentSession();
session.beginTransaction();
Org o = (Org)session.load(Org.
class
,
1
);
print(o,
0
);
session.getTransaction().commit();
}
private
void
print(Org o,
int
level) {
String preStr = ;
for
(
int
i=
0
; i<level; afterclass=
""
for
=
""
new
=
""
org=
""
pre=
""
prestr=
""
public
=
""
static
=
""
test=
""
void
=
""
>里面定义了个print()方法,里面那个level是为了使打印结果呈现树状结构<p> </p><p>打印结果:</p><p> </p><pre
class
=
"brush:java;"
>总公司
_分公司
2
__分公司
2
下的部门
1
_分公司
1
__分公司
1
下的部门
2
__分公司
1
下的部门
1
</pre>
<p> </p>
<p> </p>
<br>
<br>
<p> </p>
<p> </p>
</level;><br>
- hibernate之树状映射结构
- hibernate树状结构映射
- hibernate之树状映射
- hibernate映射应用 - 树状结构
- Hibernate基础之十一:树状结构遍历
- Hibernate 树状映射
- Hibernate表现树状结构
- hibernate树状结构
- Hibernate 树状映射简单模拟
- Hibernate——树状映射
- Hibernate——树状映射
- hibernate--树状映射(至关重要)
- hibernate继承结构映射
- hibernate笔记-016-树状结构
- Hibernate之树状结构设计
- hibernate映射之一对一映射
- hibernate映射树形结构数据
- 树状结构的设计(把一棵树存入数据库的hibernate映射,及数据库表的设计)
- HTML5独家分享:原生JS学习笔记1——基本数据类型和运算符
- Symbol 'ANDROID_LOG_DEBUG' could not be resolved
- centos linux 安装FTP服务器解决win不能上传带linux服务器上文件的问题
- c++memset一个类
- matlab中求均值的mean()函数的使用
- hibernate之树状映射结构
- Source Insight加载源码
- Google VR Concepts (1)- Developer Overview(开发概述)
- C语言字符串长度和字符串复制实现
- java中的冒泡排序
- COPY, RETAIN, ASSIGN , READONLY , READWRITE,STRONG,WEAK,NONATOMIC整理
- Google 发布 Android 性能优化典范
- 手机APP三年内将彻底消失,以后全靠H5了
- 08_Flink Streaming window