首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Hibernate 多對一與一對多關聯映射實戰:從 XML 到 CRUD 完整流程

     編輯:Java 相關知識

前言

關聯映射是 Hibernate 核心能力。本文通過 多對一(多員工共用一地址)與 一對多(一員工多證書)兩大經典場景,完整演示實體設計、XML 映射、表結構、CRUD 測試代碼。

場景一:多對一 —— 多員工共用地址

1. 實體類

public class Employee {
    private Integer id;
    private String firstName, lastName;
    private Integer salary;
    private Address address;  // 多對一關聯
    // Getter/Setter
}

public class Address {
    private Integer id;
    private String street, city, state, zipcode;
    // Getter/Setter
}

2. 表結構

CREATE TABLE EMPLOYEE (
    id INT PRIMARY KEY AUTO_INCREMENT,
    first_name VARCHAR(20), last_name VARCHAR(20), salary INT,
    address_id INT NOT NULL,
    FOREIGN KEY (address_id) REFERENCES ADDRESS(id)
);

CREATE TABLE ADDRESS (
    id INT PRIMARY KEY AUTO_INCREMENT,
    street_name VARCHAR(40), city_name VARCHAR(40),
    state_name VARCHAR(40), zipcode VARCHAR(10)
);

3. 映射文件

<class name="Employee" table="EMPLOYEE">
    <id name="id" column="id"><generator class="native"/></id>
    <property name="firstName" column="first_name"/>
    <property name="lastName" column="last_name"/>
    <property name="salary" column="salary"/>
    <many-to-one name="address" column="address_id" class="Address" not-null="true"/>
</class>

<class name="Address" table="ADDRESS">
    <id name="id" column="id"><generator class="native"/></id>
    <property name="street" column="street_name"/>
    <property name="city" column="city_name"/>
    <property name="state" column="state_name"/>
    <property name="zipcode" column="zipcode"/>
</class>

關鍵:<many-to-one> 定義關聯端,column 指定外鍵列,class 指定關聯實體,not-null="true" 保證外鍵非空。

4. CRUD 測試

// 保存地址(先保存被引用端)
Address addr = new Address("Kondapur", "Hyderabad", "AP", "532");
session.save(addr);

// 保存員工(關聯地址)
Employee e1 = new Employee("Manoj", "Kumar", 4000, addr);
Employee e2 = new Employee("Dilip", "Kumar", 3000, addr);
session.save(e1); session.save(e2);

// 查詢驗證
List<Employee> list = session.createQuery("from Employee").list();
for (Employee e : list) {
    System.out.println(e.getFirstName() + " " + e.getAddress().getCity());
}
// 輸出:Manoj Hyderabad / Dilip Hyderabad

場景二:一對多 —— 員工擁有多證書

1. 實體類

public class Employee {
    private Integer id;
    private String firstName, lastName;
    private Integer salary;
    private Set<Certificate> certificates = new HashSet<>(); // 一對多
    // Getter/Setter
}

public class Certificate {
    private Integer id;
    private String name;
    // Getter/Setter
}

2. 表結構(同場景一 EMPLOYEE 表,新增 CERTIFICATE 表)

CREATE TABLE CERTIFICATE (
    id INT PRIMARY KEY AUTO_INCREMENT,
    certificate_name VARCHAR(30),
    employee_id INT,
    FOREIGN KEY (employee_id) REFERENCES EMPLOYEE(id)
);

3. 映射文件

<class name="Employee" table="EMPLOYEE">
    <id name="id" column="id"><generator class="native"/></id>
    <set name="certificates" cascade="all">
        <key column="employee_id"/>
        <one-to-many class="Certificate"/>
    </set>
    <property name="firstName" column="first_name"/>
    <property name="lastName" column="last_name"/>
    <property name="salary" column="salary"/>
</class>

<class name="Certificate" table="CERTIFICATE">
    <id name="id" column="id"><generator class="native"/></id>
    <property name="name" column="certificate_name"/>
</class>

關鍵:<set> 保證唯一性,<key> 定義外鍵,<one-to-many> 聲明集合元素類型,cascade="all" 級聯保存/刪除。

4. CRUD 測試

// 保存員工及證書
Employee emp = new Employee("Manoj", "Kumar", 4000);
Set<Certificate> certs = new HashSet<>();
certs.add(new Certificate("MCA"));
certs.add(new Certificate("MBA"));
certs.add(new Certificate("PMP"));
emp.setCertificates(certs);
session.save(emp);  // 級聯保存證書

// 查詢並遍歷
List<Employee> list = session.createQuery("from Employee").list();
for (Employee e : list) {
    for (Certificate c : e.getCertificates()) {
        System.out.println(c.getName());
    }
}
// 輸出:MBA, PMP, MCA(Set 無序)

核心對比總結

維度多對一一對多
關係擁有方多方一放(通過集合)
映射元素<many-to-one><set>/<list>/<bag> + <one-to-many>
外鍵位置多方表多方表
級聯保存需先保存一放一放保存自動級聯多方
集合類型單值引用Set/List/Bag/Map

最佳實踐建議

  1. 雙向關聯:一對多建議在 Certificate 加 @ManyToOne / <many-to-one> 反向引用,便於從多方導航。
  2. cascade 謹慎選擇:all 含刪除,刪除員工會連帶刪除證書;若證書獨立生命週期用 save-update。
  3. 懶加載:集合預設懶加載,遍歷時需在 Session 開啟狀態,或用 fetch="join" / HQL join fetch。
  4. 現代化:新項目優先用 JPA 註解(@OneToMany/@ManyToOne),XML 僅用於歷史遷移。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved