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

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

单向多对一关联关系

  • 1.编写Dept和Emp持久化类
  • 2.使用建立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 + '\'' +
                '}';
    }
}





    
        
            
        
        
        
        
        
    
    

元素建立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.使用元素映射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 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 getEmps() {
        return emps;
    }

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

    public Department() {
    }

    public Department(Byte deptNo, String deptName, String location, Set 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 +
                '}';
    }
}




    
        
            
        
        
        
        
            
            
        
    
    

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

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

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

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

元素表明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语句会影响应用的性能。




    
        
            
        
        
        
        
            
            
        
    


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多对一和一对多的关联关系)