Hibernate的自身关联映射(十)

简介: Hibernate的自身关联映射(十)

一. 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);
  }


运行之后,步骤是:


  1. 创建dept表
  2. 修改表结构,添加外键parentId
  3. 插入数据


2019021612385141.png


其实,自身关联的配置与一对多的双向配置是一样的,但刚开始的时候,老蝴蝶并不明白,查了很多资料。相信有些人也不太明白,所以单独列了出来。


五.二 测试查询的方法


/*自身关联的查询*/
  @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);
    }
  }


20190216124636974.png


均是正常的查询。


五.三 扩充


  1. 在toString()方法中,添加输出parent 会怎么样?


20190216124828906.png


正常。


2.只添加children 会怎么样?


20190216124934175.png


也是正常的。


3.如果同时添加呢? 会形成一个死循环,也会造成栈溢出错误。


20190216125052630.png


切记,在自身关联时,不要把parent和children属性同时输出。 扩大话就是,不一定要在toString()中输出全部的属性来表示这个对象,只需要输出几个标志性的即可。


谢谢!!!

相关文章
|
存储 SQL Oracle
Hibernate-05-主键生成策略
Hibernate-05-主键生成策略
Hibernate-05-主键生成策略
|
XML Java 关系型数据库
hibernate里面的一对多关系映射
hibernate里面的一对多关系映射
111 0
|
SQL NoSQL Java
hibernate(五) hibernate一对一关系映射详解
之前讲解了一对多(单向、双向)、多对多(双向),今天就讲解一下最后一个关系,一对一。 心情不错。状态也挺好的,赶紧写一篇博文造福一下大家把。  
285 0
|
Java 关系型数据库 数据库连接
Hibernate-ORM:12.Hibernate中的多对多关联关系
    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥-------------       本篇博客将讲述Hibernate中的多对多关联关系的操作,准备的篇幅较少,望海涵   一,讲述多对多   多对多的关联关系,比如学生和教师来说,一个学生由多个教师授课...
1272 0
|
Java 数据库连接
【Jpa hibernate】一对多@OneToMany,多对一@ManyToOne的使用
项目中使用实体之间存在一对多@OneToMany,多对一@ManyToOne的映射关系,怎么设置呢? GitHub地址:https://github.com/AngelSXD/myagenorderdiscount可以查看完整项目 下面给一个例子: 类似于一个部门对应多个员工 这里给出 一个流水账单对应多条订单折扣信息   流水账单类: package com.
8875 0
|
Oracle 关系型数据库 Java
Hibernate主键生成策略及选择
1 .increment:适用于short,int,long作为主键,不是使用数据库自动增长机制 这是hibernate中提供的一种增长机制            在程序运行时,先进行查询:select max(id) from user;                              ...
762 0
|
Java 关系型数据库 数据库连接
|
Web App开发 Java 数据库连接