在 Hibernate 中從資料庫取得實體列表
一、簡介
Hibernate 是一個強大的 ORM(物件關聯映射)框架,它簡化了 Java 物件和關聯式資料庫之間的互動。 Hibernate 抽象化了編寫原始 SQL 查詢的複雜性,使我們能夠使用更物件導向的方法來擷取實體清單。在本教程中,我們將探索一些使用 Hibernate 從資料庫中檢索實體清單的技術。
2. 將資料庫表映射到實體
Hibernate 提供了一種將資料庫表對應到 Java 類別(稱為實體)的簡單方法。每個實體類別代表資料庫中的一個表,其屬性對應到表中的列。 @Entity
、 @Table
、 @Id
和@Column
等註解用於定義 Java 類別和對應資料庫表之間的對應。
此外,Hibernate 利用實體對應將我們的查詢(使用 JPQL 或 Criteria API)轉換為高效率的 SQL 語句。當我們編寫像「 SELECT e FROM Employee e
」這樣的 JPQL 查詢時,Hibernate 會理解「 Employee
」是指代表「 Employee
」表的實體類,而「 e
」代表該實體的實例。然後它將其轉換為適當的 SQL 語句以從基礎資料庫表中檢索資料。
3. 使用條件API
Criteria API 提供了一種使用 Java 物件以程式設計方式建構查詢的替代方法。它允許我們在運行時動態建立查詢,當查詢條件在編譯時未知或需要根據使用者輸入或應用程式邏輯動態建置時,這特別有用。
以下是使用 Criteria API 檢索實體清單的方法:
@PersistenceContext
private EntityManager entityManager;
public List<Employee> getAllEmployees() {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);
Root<Employee> employeeRoot = criteriaQuery.from(Employee.class);
criteriaQuery.select(employeeRoot);
Query query = entityManager.createQuery(criteriaQuery);
return query.getResultList();
}
此範例檢索所有Employee
實體。 CriteriaBuilder
用來建構查詢。我們定義根實體 ( Employee.class
) 並指定我們要從此實體中選擇所有屬性 ( criteriaQuery.select(employeeRoot)
)。最後,查詢被轉換為類型化的Query
物件並使用getResultList()
執行。
Criteria API 允許建立動態過濾和排序標準。以下是從「 Engineering
」部門擷取員工(依姓氏升序排列)的範例:
public List<Employee> getAllEmployeesByDepartment(String department) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);
Root<Employee> employeeRoot = criteriaQuery.from(Employee.class);
Predicate departmentPredicate = criteriaBuilder.equal(employeeRoot.get("department"), department);
Path<Object> sortByPath = employeeRoot.get("lastName");
criteriaQuery.orderBy(criteriaBuilder.asc(sortByPath));
criteriaQuery.select(employeeRoot).where(departmentPredicate);
Query query = entityManager.createQuery(criteriaQuery);
return query.getResultList();
}
此範例使用criteriaBuilder.equal()
方法定義departmentPredicate
並將其套用至查詢。按姓氏排序是使用criteriaBuilder.asc()
實現的。
4.使用JPQL(Java持久性查詢語言)
JPQL 提供了一種便捷的方式來編寫類似於 SQL 語法的查詢,但對實體和屬性名稱而不是表格和列進行操作。這簡化了查詢建構並提高了可讀性。
以下是使用 JPQL 檢索所有Employee
實體的方法:
@PersistenceContext
private EntityManager entityManager;
public List<Employee> getAllEmployees() {
String jpqlQuery = "SELECT e FROM Employee e";
Query query = entityManager.createQuery(jpqlQuery, Employee.class);
return query.getResultList();
}
我們建構一個 JPQL 查詢字串SELECT e FROM Employee e
來檢索所有Employee
實體。接下來,我們使用EntityManager
的createQuery()
方法建立 JPQL 查詢物件並設定查詢字串和預期結果類型 ( Employee.class
)。最後,我們使用getResultList()
方法執行查詢,該方法傳回從資料庫取得的Employee
實體清單。
JPQL 提供使用WHERE
子句過濾結果並使用ORDER BY
對結果進行排序的功能。以下的範例示範如何從特定部門擷取按姓氏升序排列的員工:
public List<Employee> getAllEmployeesByDepartment() {
String jpqlQuery = "SELECT e FROM Employee e WHERE e.department = 'Engineering' ORDER BY e.lastName ASC";
Query query = entityManager.createQuery(jpqlQuery, Employee.class);
return query.getResultList();
}
此查詢會擷取department
屬性等於「 Engineering
」的所有Employee
實體 ( e
),並依其lastName
屬性升序 ( ASC
) 對它們進行排序。
5. 使用命名查詢
雖然 JPQL 提供了一種動態建構查詢的便捷方法,但命名查詢提供了一種結構化方法,用於在實體類別或單獨的 XML 設定檔中預先定義可重複使用查詢。這提高了程式碼的可讀性和可維護性,並降低了查詢字串中出現錯誤的風險。
在 Hibernate 中定義命名查詢有兩種主要方法。
5.1.使用註釋
我們可以直接在實體類別中使用@NamedQuery
註解定義命名查詢:
@Entity
@NamedQuery(name = "findAllEmployees", query = "SELECT e FROM Employee e")
@NamedQuery(name = "findEmployeesByDepartment", query = "SELECT e FROM Employee e WHERE e.department = :department ORDER BY e.lastName ASC")
public class Employee {
@Id
@GeneratedValue
private Integer id;
private String lastName;
private String department;
// getter and setter methods
}
在這個範例中,我們使用@NamedQuery
註解在Employee
實體類別中定義兩個命名查詢。第一個命名查詢findAllEmployees
從資料庫中檢索所有員工,無需任何過濾條件。
第二個命名查詢findEmployeesByDepartment
比較具體。它根據相關部門檢索員工。透過提供部門作為參數( :department
),我們可以根據指定的部門過濾員工。此外,查詢會依照員工的姓氏以升序對結果進行排序 ( ORDER BY e.lastName ASC
)。
5.2.使用 XML 配置
我們可以建立一個 XML 檔案hibernate.cfg.xml
來定義命名查詢。我們使用<named-query>
元素來指定查詢名稱、JPQL 字串和目標實體:
<hibernate-configuration>
<named-query name="findAllEmployees">
<query>SELECT e FROM Employee e</query>
</named-query>
<named-query name="findEmployeesByDepartment">
<query>SELECT e FROM Employee e WHERE e.department = :department ORDER BY e.lastName ASC</query>
</named-query>
</hibernate-configuration>
此組態定義了與註解方法中相同的兩個命名查詢( findAllEmployees
和findEmployeesByDepartment
)。 XML 配置提供了更好的關注點分離和集中管理,而註釋提供了更簡潔和以實體為中心的方式來定義命名查詢。
5.3.使用命名查詢
若要使用命名查詢,我們可以使用entityManager.createNamedQuery()
方法。此方法允許我們建立並執行在實體類別或 XML 配置中定義的命名查詢。
下面的程式碼片段示範了命名查詢的用法:
@PersistenceContext
private EntityManager entityManager;
public List<Employee> getAllEmployees() {
Query query = entityManager.createNamedQuery("findAllEmployees", Employee.class);
return query.getResultList();
}
public List<Employee> findEmployeesByDepartment(String department) {
Query query = entityManager.createNamedQuery("findEmployeesByDepartment", Employee.class);
query.setParameter("department", department);
return query.getResultList();
}
在此範例中,我們檢索所有員工 ( findAllEmployees
) 並使用命名查詢按部門 ( findEmployeesByDepartment
) 過濾它們。
6. 一對多關係
在Hibernate中,我們可以使用getter方法輕鬆地從父實體存取關聯實體的集合。一對多關係允許單一實體(父實體)與相關實體(子實體)的集合關聯。此功能在檢索父實體清單時特別有用,因為我們可能還希望在單一查詢中存取其關聯的子實體。
下面的程式碼範例示範如何使用getEmployees()
方法來擷取Department
實體及其關聯的Employee
實體的清單:
@Entity
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
<span class="citation-0 citation-end-0">@OneToMany(mappedBy = "department",</span> fetch = FetchType.EAGER)
private List<Employee> employees;
// Getters and setters...
}
在此映射配置中, Department
實體與Employee
實體具有OneToMany
關聯,由Employee
實體中的department
欄位進行對應。 Department
實體中的employees
欄位表示關聯員工的集合。
現在,我們可以使用getEmployees()
方法直接存取特定部門的員工集合:
public List<Employee> getAllEmployeesByDepartment(String departmentName) {
Department department = entityManager.createQuery("SELECT d FROM Department d WHERE d.name = :name", Department.class)
.setParameter("name", "Engineering")
.getSingleResult();
return department.getEmployees();
}
在此範例中, employees
欄位上的@OneToMany
註解使用fetch = FetchType.EAGER.
這指示 Hibernate 在單一查詢中檢索所有關聯的Employee
和Department
實體。
七、結論
在本文中,我們探索了使用 Hibernate 檢索實體清單的各種方法:JPQL、Criteria API 和一對多關係。 JPQL 提供了一種簡單直觀的方式來建立查詢,使其適合基本查詢或具有已知條件的查詢。但是,Criteria API 可能很有用,特別是在編譯時未知查詢條件或需要根據應用程式邏輯或使用者輸入動態調整查詢條件的情況下。
與往常一樣,範例的原始程式碼可在 GitHub 上取得。