Hibernate多对一和一对多的关联关系

部门和员工 一个部门多个员工,一个员工只属于一个部门。

单向多对一关联关系

  • 1.编写Dept和Emp持久化类
  • 2.使用<many-to-one>建立EMP表的外键DEPYNO和dept属性之间的映射
  • 3.验证对象持久化方法
package com.pojo;

import java.io.Serializable;

public class Emp implements Serializable {
    private Integer empNo;//员工编号
    private String empName;//员工姓名
    private String job;//员工职位
    private double salary;//员工薪水
    private Department department;//所属部门

    public Integer getEmpNo() {
        return empNo;
    }

    public void setEmpNo(Integer empNo) {
        this.empNo = empNo;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    public Emp() {

    }

    public Emp(Integer empNo, String empName, String job, double salary, Department department) {
        this.empNo = empNo;
        this.empName = empName;
        this.job = job;
        this.salary = salary;
        this.department = department;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empNo=" + empNo +
                ", empName='" + empName + '\'' +
                ", job='" + job + '\'' +
                ", salary=" + salary +
                ", department=" + department +
                '}';
    }
}
package com.pojo;

import java.io.Serializable;

public class Department implements Serializable {
    private Byte deptNo;//部门编号
    private String deptName;//部门名称
    private String location;//部门地址


    public Byte getDeptNo() {
        return deptNo;
    }

    public void setDeptNo(Byte deptNo) {
        this.deptNo = deptNo;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }


    public Department() {
    }

    public Department(Byte deptNo, String deptName, String location) {
        this.deptNo = deptNo;
        this.deptName = deptName;
        this.location = location;
    }

    @Override
    public String toString() {
        return "Department{" +
                "deptNo=" + deptNo +
                ", deptName='" + deptName + '\'' +
                ", location='" + location + '\'' +
                '}';
    }
}

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

    <class name="com.pojo.Emp" table="Emp" catalog="project">
        <id name="empNo" column="empNo" type="java.lang.Integer">
            <generator class="assigned"></generator>
        </id>
        <property name="empName" column="empName" type="java.lang.String"></property>
        <property name="job" column="job" type="java.lang.String"></property>
        <property name="salary" column="salary" type="java.lang.Double"></property>
        <many-to-one name="department" column="deptNo" class="com.pojo.Department"></many-to-one>
    </class>
    
</hibernate-mapping>

<many-to-one>元素建立emp表的外键deotNo和department属性之间的映射

  • name:设定持久化类的属性名,这里是Emp类的department属性
  • column:设定持久化类的属性对应表的外键,这里是emp表的外键
  • class:设定持久化类的属性类型,设定department属性为Dept类型
  /**
     * 存储员工
     */
    public void save(Emp emp) {
        this.getCurrentSession().save(emp);
    }
public void save() {
        Emp emp = new Emp();
        emp.setEmpNo(10002);
        emp.setEmpName("张三");
        emp.setJob("研发");
        emp.setSalary(13000.50);
        Department department=new Department();
        department.setDeptNo((byte)10);
        emp.setDepartment(department);
        empBiz.save(emp);
    }

Hibernate:
select
department_.deptNo,
department_.deptName as deptName0_,
department_.location as location0_
from
project.Department department_
where
department_.deptNo=?
Hibernate:
insert
into
project.Emp
(empName, job, salary, deptNo, empNo)
values
(?, ?, ?, ?, ?)

总结

  • 先查询外键的部门编号是否存在,如果存在插入信息,如果不存在,抛出异常报错
    Caused by: java.sql.BatchUpdateException: Cannot add or update a child row: a foreign key constraint fails (project.emp, CONSTRAINT FK110A816FF5875 FOREIGN KEY (deptNo) REFERENCES department (deptNo))

双向一对多关联关系

  • 1.在Department类中增加一个集合类型的emps属性
  • 2.使用<set>元素映射emps属性
  • 3.验证双向一对多关联元素对象持久化方法
package com.pojo;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public class Department implements Serializable {
    private Byte deptNo;//部门编号
    private String deptName;//部门名称
    private String location;//部门地址
    private Set<Emp> emps=new HashSet<>();//部门员工集合


    public Byte getDeptNo() {
        return deptNo;
    }

    public void setDeptNo(Byte deptNo) {
        this.deptNo = deptNo;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }


    public Set<Emp> getEmps() {
        return emps;
    }

    public void setEmps(Set<Emp> emps) {
        this.emps = emps;
    }

    public Department() {
    }

    public Department(Byte deptNo, String deptName, String location, Set<Emp> emps) {
        this.deptNo = deptNo;
        this.deptName = deptName;
        this.location = location;
        this.emps = emps;
    }

    @Override
    public String toString() {
        return "Department{" +
                "deptNo=" + deptNo +
                ", deptName='" + deptName + '\'' +
                ", location='" + location + '\'' +
                ", emps=" + emps +
                '}';
    }
}

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.pojo.Department" table="Department" catalog="project">
        <id name="deptNo" type="java.lang.Byte" column="deptNo">
            <generator class="assigned"></generator>
        </id>
        <property name="deptName" type="java.lang.String" column="deptName"></property>
        <property name="location" type="java.lang.String" column="location"></property>
        <set name="emps" cascade="all">
            <key column="deptNo"></key>
            <one-to-many class="com.pojo.Emp"></one-to-many>
        </set>
    </class>
    
</hibernate-mapping>

<set>元素表明Department类的emps属性是Set集合

  • name:设定持久化类的属性名,为Department类的emps属性
  • cascade:保存删除Dept对象的同时级联保存或删除与Dept对象关联的Emp对象

<key>元素表明emp表通过外键deptNo参考department表

  • column:设定与所关联的持久化类相对应的表的外键,为emp表的deptNo字段

<one-to-many>元素表明emps集合存放的是一组Emp对象

cascade属性的取值

  • 1.none 当Session操作当前对象时,忽略其他关联对象,他是cascade属性默认值
  • 2.save-update当通过Session的save(),update()及saveOrUpdate()方法来保存或跟新当前对象时,级联保存所有关联的瞬时状态的对象,并且级联更新所有关联的游离对象
  • 3.delete当通过Session的delete()方法删除当前对象时,会级联删除所有关联对象
  • 4.包含save-update,delete方法

级联插入

  public void save(Department department) {
        this.getCurrentSession().save(department);
    }
 //创建一个部门
        Department department = new Department();
        department.setDeptNo((byte) 16);
        department.setDeptName("研发部");
        department.setLocation("广州");
        //创建一个员工
        Emp emp=new Emp();
        emp.setEmpName("李四");
        emp.setEmpNo(1008);
        emp.setJob("研发");
        emp.setSalary(19500.50);
        //建立Dept对象和Emp对象双向关联关系
        emp.setDepartment(department);
        department.getEmps().add(emp);
        departmentBiz.saveDept(department);

Hibernate:
select
emp_.empNo,
emp_.empName as empName1_,
emp_.job as job1_,
emp_.salary as salary1_,
emp_.deptNo as deptNo1_
from
project.Emp emp_
where
emp_.empNo=?
Hibernate:
insert
into
project.Department
(deptName, location, deptNo)
values
(?, ?, ?)
Hibernate:
insert
into
project.Emp
(empName, job, salary, deptNo, empNo)
values
(?, ?, ?, ?, ?)
Hibernate:
update
project.Emp
set
deptNo=?
where
empNo=?

总结
首先因为主键生成策列是assigned先查询是否存在该OID的emp对象,之后插入Dept对象,再插入Emp对象,最后更新Emp表的外键与Dept表同步。

级联删除

 public void delete(Department department) {
        this.getCurrentSession().delete(department);
    }
public void delete() {
        Department department = departmentBiz.getDept((byte) 89);
        departmentBiz.deleteDept(department);
    }

Hibernate:
select
department0_.deptNo as deptNo0_0_,
department0_.deptName as deptName0_0_,
department0_.location as location0_0_
from
project.Department department0_
where
department0_.deptNo=?
Hibernate:
select
department_.deptNo,
department_.deptName as deptName0_,
department_.location as location0_
from
project.Department department_
where
department_.deptNo=?
Hibernate:
select
emps0_.deptNo as deptNo0_1_,
emps0_.empNo as empNo1_,
emps0_.empNo as empNo1_0_,
emps0_.empName as empName1_0_,
emps0_.job as job1_0_,
emps0_.salary as salary1_0_,
emps0_.deptNo as deptNo1_0_
from
project.Emp emps0_
where
emps0_.deptNo=?
Hibernate:
update
project.Emp
set
deptNo=null
where
deptNo=?
Hibernate:
delete
from
project.Emp
where
empNo=?
Hibernate:
delete
from
project.Department
where
deptNo=?

总结
首先主键生成策列是assigned根据部门编号查询了两次部门信息,再根据部门编号查询了部门员工,根据部门编号更新员工表外键置为null,随后根据员工编号删除员工信息,最后根据部门编号删除部门

inverse属性指定了关联关系中的方向,默认是false。在关联关系中,inverse="false"的一方是主动方,主动方会负责维护关联关系。例如部门一方会主动执行update语句即update emp set deptNo=? where empno=?用来维护外键的取值。但是 emp.setDepartment(department);
设定了正确的关联关系,该语句实际上是多余的,执行多余的update语句会影响应用的性能。

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.pojo.Department" table="Department" catalog="project">
        <id name="deptNo" type="java.lang.Byte" column="deptNo">
            <generator class="assigned"></generator>
        </id>
        <property name="deptName" type="java.lang.String" column="deptName"></property>
        <property name="location" type="java.lang.String" column="location"></property>
        <set name="emps" cascade="all" inverse="true">
            <key column="deptNo"></key>
            <one-to-many class="com.pojo.Emp"></one-to-many>
        </set>
    </class>

</hibernate-mapping>

Hibernate:
select
emp_.empNo,
emp_.empName as empName1_,
emp_.job as job1_,
emp_.salary as salary1_,
emp_.deptNo as deptNo1_
from
project.Emp emp_
where
emp_.empNo=?
Hibernate:
insert
into
project.Department
(deptName, location, deptNo)
values
(?, ?, ?)
Hibernate:
insert
into
project.Emp
(empName, job, salary, deptNo, empNo)
values
(?, ?, ?, ?, ?)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,692评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,482评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,995评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,223评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,245评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,208评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,091评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,929评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,346评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,570评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,739评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,437评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,037评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,677评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,833评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,760评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,647评论 2 354

推荐阅读更多精彩内容