一. Hibernate的自身关联映射
这句话是什么意思呢? 简单理解就是,一个类自己进行相关联。 如部门Dept 类。 这个部门的父级部门有一个,也是部门,有多个子部门,也是部门。 还有科目类Subject,雇员类User, 即存在上下级的关系的。
这里用典型的Dept 类进行讲解。 在表结构中,应该表现出来的是,dept表后面有一个parentId 这个外键来自身关联。
二.搭建Hibernate环境,与前面相同。
三. 编写Dept实体类
package com.yjl.pojo; import java.util.HashSet; import java.util.Set; /** @author: yuejl @date: 2019年2月16日 上午10:15:08 @Description 数据库中一的一方 部门实体 */ public class Dept { /** * @param id 部门的编号 * @param name 部门的名称 * @param description 部门的描述 */ private Integer id; private String name; private String description; /** * @param parent 上级部门,只有一个 * @param children 下级 部门,可能存在多个,也可能 一个,或者没有。用Set */ private Dept parent; private Set<Dept> children=new HashSet<Dept>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Dept getParent() { return parent; } public void setParent(Dept parent) { this.parent = parent; } public Set<Dept> getChildren() { return children; } public void setChildren(Set<Dept> children) { this.children = children; } @Override public String toString() { return "Dept [id=" + id + ", name=" + name + ", description=" + description + "]"; } }
四. 编写对应的Dept.hbm.xml文件
<hibernate-mapping package="com.yjl.pojo" > <!-- 具体的实体类 由于前面指定了package包名。这里只需要写Dept即可。否则写com.yjl.pojo.Dept 全限定名称--> <class name="Dept" table="dept"> <!-- 主键 --> <id name="id" column="id"> <generator class="native"></generator> </id> <!-- 其余属性 这里type运用的是java类型,并不是Hibernate和数据库的--> <property name="name" length="20" type="java.lang.String"></property> <property name="description" length="100" type="java.lang.String"></property> <!-- 对每一个字段进行分析。 先对parent进行分析。 多对一 --> <many-to-one name="parent" column="parentId" class="Dept"></many-to-one> <!-- 对children进行分析。 一对多 --> <set name="children"> <!-- 与上面的many-to-one中的值保存一致 --> <key column="parentId"></key> <one-to-many class="Dept"/> </set> </class> </hibernate-mapping>
五.编写测试的文件
五.一 测试保存的方法
/*自身关联的保存方法*/ @Test public void saveTest(){ Session session=HibernateUtil.getSession(); /*1.创建数据,设置一级的*/ Dept root=new Dept(); root.setName("总裁室"); /*2.设置二级的*/ Dept d21=new Dept(); d21.setName("财务室"); Dept d22=new Dept(); d22.setName("行政部"); Dept d23=new Dept(); d23.setName("管理部"); /*3.设置三级的*/ Dept d31=new Dept(); d31.setName("开发部"); Dept d32=new Dept(); d32.setName("信息部"); Dept d33=new Dept(); d33.setName("人事部"); /*4.设置关系*/ d21.setParent(root); d22.setParent(root); d23.setParent(root); d31.setParent(d23); d32.setParent(d23); d33.setParent(d22); /*保存。 从上到下保存*/ session.save(root); session.save(d21); session.save(d22); session.save(d23); session.save(d31); session.save(d32); session.save(d33); }
运行之后,步骤是:
- 创建dept表
- 修改表结构,添加外键parentId
- 插入数据
其实,自身关联的配置与一对多的双向配置是一样的,但刚开始的时候,老蝴蝶并不明白,查了很多资料。相信有些人也不太明白,所以单独列了出来。
五.二 测试查询的方法
/*自身关联的查询*/ @Test public void searchTest(){ Session session=HibernateUtil.getSession(); /*1 管理部做查询*/ Dept d=session.get(Dept.class,4); System.out.println("自身查询:"+d); /*2 上级部门的*/ Dept parent=d.getParent(); System.out.println("上级部门的:"+parent); /*3 下级部门的*/ Set<Dept> children=d.getChildren(); System.out.println("下级部门的:"); for (Dept dept : children) { System.out.println(dept); } /*4.上级部门的下级部门*/ Set<Dept> children1=parent.getChildren(); System.out.println("上级部门的下级部门的:"); for (Dept dept : children1) { System.out.println(dept); } }
均是正常的查询。
五.三 扩充
- 在toString()方法中,添加输出parent 会怎么样?
正常。
2.只添加children 会怎么样?
也是正常的。
3.如果同时添加呢? 会形成一个死循环,也会造成栈溢出错误。
切记,在自身关联时,不要把parent和children属性同时输出。 扩大话就是,不一定要在toString()中输出全部的属性来表示这个对象,只需要输出几个标志性的即可。
谢谢!!!