3. JPA對象關係映射 -- 級聯操做

對象映射關係分爲單向關係和雙向關係,單向關係只在一方對象上存在對方對象,雙向關係是在雙方對象上存在彼此對象。java

1、單向關係

public class Department implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer departmentId;

    private String departmentCode;
    
    @OneToMany(cascade = {CascadeType.ALL})
    @JoinColumn
    private List<Employee> employeeList;
}

在沒有@JoinColumn時,將多增長一箇中間關係表,由此表來維護兩個對象關係,增長以後只有兩個表,由Employee表維護關係。默認狀況下jpa會使用主鍵來作關聯,並在子表中增長外鍵約束。git

2、單向關係使用code關聯

在設計表結構時,主鍵通常會使用自增ID,但在作子表關聯時因爲分佈式結構緣由不想使用自增ID來作關係維護,則可自定義字段code來維護關係,以下:sql

public class Department implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer departmentId;

    private String departmentCode;

    @OneToMany(cascade = {CascadeType.ALL})
    @JoinColumn(name = "departmentCode", referencedColumnName = "departmentCode")
    private List<Employee> employeeList;
}

在employee表中會增長一個department_code字段來維護關聯關係。
注意:從add操做中的SQL能夠看出,employee是先insert以後,再去update關係字段的,多一步update。數據庫

Hibernate: insert into department (department_code, department_name) values (?, ?)
Hibernate: insert into employee (employee_code, employee_name) values (?, ?)
Hibernate: insert into employee (employee_code, employee_name) values (?, ?)
Hibernate: update employee set department_code=? where employee_id=?
Hibernate: update employee set department_code=? where employee_id=?

3、雙向關係

public class Department implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer departmentId;

    private String departmentCode;

    @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "department")
    private List<Employee> employeeList;
}

public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer employeeId;

    private String employeeCode;

    @ManyToOne
    private Department department;
}

使用mappedBy將去掉中間關係表,由employee維護department的關係。併發

注意事項
1.在add操做中子對象employee必須設置主對象,不然數據庫層面是沒有維護外鍵關係的,如:app

@Test
public void add(){
    Department department = Department.builder()
            .departmentCode("D001")
            .departmentName("部門1")
            .build();

    Employee employee = Employee.builder()
            .employeeCode("E001")
            .employeeName("員工1")
            .build();
    // 如無此操做,將無關聯關係        
    employee.setDepartment(department);
    
    List<Employee> employeeList = new ArrayList<>();
    employeeList.add(employee);

    department.setEmployeeList(employeeList);
    departmentRepository.save(department);
}

2.此種設置是不須要額外update關係的分佈式

Hibernate: insert into department (department_code, department_name) values (?, ?)
Hibernate: insert into employee (department_department_id, employee_code, employee_name) values (?, ?, ?)
Hibernate: insert into employee (department_department_id, employee_code, employee_name) values (?, ?, ?)

3.關閉子對象中的父對象toString,避免無限循環調用ui

4、雙向關係使用code關聯

同單向關係相似,且有額外的update操做
code關聯,使用JoinColumn時不可同時使用mappedByspa

5、級聯操做設置

  • CascadeType.PERSIST:級聯保存,在保存department的同時保存employee對象
  • CascadeType.MERGE:級聯更新,將department和employee視爲一個總體,任何一個對象有變化,都會更新
  • CascadeType.REMOVE:級聯刪除設計

    • 當沒有設置時,delete主對象時,子對象只是去掉關係;remove子對象時也只是去掉關係,若是增長orphanRemoval = true則會刪除remove的子對象
    • 當有設置時,delete主對象時,子對象一樣會被刪除
  • CascadeType.REFRESH:級聯刷新(較少使用),在併發的場景下避免髒數據
  • CascadeType.DETACH:級聯脫管(較少使用)
  • CascadeType.ALL:以上所有,須要根據實際狀況謹慎設置,以避免產生混亂

6、源代碼

https://gitee.com/hypier/barr...

此處輸入圖片的描述

相關文章
相關標籤/搜索