Spring Data JPA 中的查詢提示
一、簡介
在本教程中,我們將探討 Spring Data JPA 中查詢提示的基礎知識。這些提示有助於優化資料庫查詢,並可能透過影響優化器的決策過程來提高應用程式效能。我們還將討論它們的功能以及如何有效地應用它們。
2. 理解查詢提示
Spring Data JPA 中的查詢提示是一個強大的工具,可以幫助最佳化資料庫查詢並提高應用程式效能。與直接控制執行不同,它們影響優化器的決策過程。
在 Spring Data JPA 中,我們在org.hibernate.annotations
套件中找到這些提示,以及與流行的持久性提供者 Hibernate 相關的各種註解和類別。值得注意的是,這些提示的解釋和執行通常取決於底層持久性提供程序,例如 Hibernate 或 EclipseLink,這使得它們特定於供應商。
3. 使用查詢提示
Spring Data JPA 提供了多種利用查詢提示來最佳化資料庫查詢的方法。讓我們探討一下常見的方法。
3.1.基於註解的配置
Spring Data JPA 提供了一種使用註解為 JPA 查詢新增查詢提示的簡單方法。 @QueryHints
註解支援指定用於套用於產生的 SQL 查詢的 JPA @QueryHint
提示陣列。
讓我們考慮以下範例,其中我們設定 JDBC 取得大小提示來限制結果傳回大小:
@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
@QueryHints(value = { @QueryHint(name = "org.hibernate.fetchSize", value = "50") })
List<Employee> findByGender(String gender);
}
在此範例中,我們將@QueryHints
註解新增至EmployeeRepository
介面的findByGender()
方法中,以控制一次取得的實體數量。此外,我們可以在儲存庫層級應用@QueryHints
註解來影響儲存庫中的所有查詢:
@Repository
@QueryHints(value = { @QueryHint(name = "org.hibernate.fetchSize", value = "50") })
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
// Repository methods...
}
此操作可確保指定的查詢提示適用於EmployeeRepository
介面內的所有查詢,進而提高儲存庫查詢之間的一致性。
3.2.以程式設計方式設定查詢提示
除了基於註解的動態方法之外,我們還可以使用EntityManager
物件以程式設計查詢提示。此方法提供對查詢提示配置的精細控制。以下是以程式設計方式設定自訂 SQL 註解提示的範例:
@PersistenceContext
private EntityManager entityManager;
@Override
List<Employee> findRecentEmployees(int limit, <span class="hljs-type">boolean</span> readOnly) {
Query query = entityManager.createQuery("SELECT e FROM Employee e ORDER BY e.joinDate DESC", Employee.class)
.setMaxResults(limit)
.setHint(<span class="hljs-string">"org.hibernate.readOnly"</span>, readOnly);
return query.getResultList();
}
在此範例中,我們傳遞一個boolean
標誌作為參數來指示提示應設為true
還是false.
這種靈活性使我們能夠根據運行時條件調整查詢行為。
3.3.在實體中定義命名查詢
可以直接在Entity
類別中使用@NamedQuery
註解來套用查詢提示。這允許我們定義一個命名查詢以及特定的提示。例如,讓我們考慮以下程式碼片段:
@Entity
@NamedQuery(name = "selectEmployee", query = "SELECT e FROM Employee e",
hints = @QueryHint(name = "org.hibernate.fetchSize", value = "50"))
public class Employee {
// Entity properties and methods
}
在Entity
類別中定義後,可以使用EntityManager
的createNamedQuery()
方法呼叫具有關聯提示的命名查詢selectEmployee
:
List<Employee> employees = em.createNamedQuery("selectEmployee").getResultList();
4. 查詢提示使用場景
查詢提示可用於多種場景,以最佳化查詢效能。以下是一些常見的用例。
4.1.逾時管理
在查詢可能運作較長時間的情況下,實施有效的逾時管理策略變得至關重要。透過利用javax.persistence.query.timeout
提示,我們可以建立查詢的最大執行時間。這種做法可確保查詢不會超過指定的時間閾值。
此提示接受一個以毫秒為單位的值,如果查詢超出限制,則會拋出LockTimeoutException
。以下是我們為檢索活躍員工設定的超時時間為5000
毫秒的範例:
@QueryHints(value = {@QueryHint(name = "javax.persistence.query.timeout<em>"</em>, value = "5000")})
List<Employee> findActiveEmployees(long inactiveDaysThreshold);
4.2.快取查詢結果
查詢提示可用於使用jakarta.persistence.cache.retrieveMode
提示啟用查詢結果快取。當設定為USE
時,JPA 在存取資料庫之前首先嘗試從快取中檢索實體。另一方面,將其設定為BYPASS
指示 JPA 忽略快取並直接從資料庫取得實體。
此外,我們也可以使用jakarta.persistence.cache.storeMode
來指定 JPA 如何處理二級快取中的儲存實體。當設定為USE
時,JPA 將實體新增至快取並更新現有實體。 BYPASS
模式指示 Hibernate 僅更新快取中的現有實體,而不新增實體。最後, REFRESH
模式在檢索實體之前刷新快取中的實體,確保快取的資料是最新的。
下面是一個範例,示範了這些提示的用法:
@QueryHints(value = {
@QueryHint(name = "jakarta.persistence.cache.retrieveMode", value = "USE"),
@QueryHint(name = "jakarta.persistence.cache.storeMode", value = "USE")
})
List<Employee> findEmployeesByName(String name);
在這種情況下, retrieveMode
和storeMode
都配置為USE
,表示 Hibernate 主動利用二級快取來擷取和儲存實體。
4.3.最佳化查詢執行計劃
查詢提示可用於影響資料庫最佳化器產生的執行計劃。例如,當資料保持不變時,我們可以使用 o rg.hibernate.readOnly
提示來表示查詢是唯讀的:
@QueryHints(@QueryHint(name = "org.hibernate.readOnly", value = "true"))
User findByUsername(String username);
4.4.自訂 SQL 註釋
org.hibernate.comment
提示允許在查詢中新增自訂 SQL 註釋,以協助查詢分析和除錯。當我們想要在產生的 SQL 語句中提供上下文或註解時,此函數特別有用。
這是一個例子:
@QueryHints(value = { @QueryHint(name = "org.hibernate.comment", value = "Retrieve employee older than specified age\"") })
List findByAgeGreaterThan(int age);
5. 結論
在本文中,我們了解了 Spring Data JPA 中查詢提示的重要性及其對最佳化資料庫查詢以提高應用程式效能的重大影響。我們探索了各種技術,包括基於註釋的配置和直接 JPQL 操作,以有效地應用查詢提示。
與往常一樣,範例的原始程式碼可在 GitHub 上取得。