Java Persistence API (JPA) 提供了多種資料存取方式:透過 EntityManager 的 find() 方法、JPQL 動態查詢、原生 SQL 查詢,以及被廣泛討論的「命名查詢」。雖然 JPA 規範允許使用 XML 或註解兩種映射方式,但實務上註解因文檔範例多採用此方式而成為主流。然而,將命名查詢以註解形式硬編碼在實體類中,真的符合「外部化查詢」的初衷嗎?本文將深入剖析各類查詢風格,揭示註解式命名查詢的侷限性,並探討更靈活的替代方案。
最基礎的方式,適用於已知主鍵的單筆查詢:
Customer customer = em.find(Customer.class, customerId);
運行時組裝查詢字串,適合條件不固定的場景:
Query q = em.createQuery("SELECT c FROM Customer c WHERE c.name LIKE :custName");
q.setParameter("custName", name);
q.setMaxResults(10);
List result = q.getResultList();
需發揮資料庫特有功能或處理複雜關聯時使用:
Query q = em.createNativeQuery(
"SELECT o.id, o.quantity, o.item, i.id, i.name, i.description " +
"FROM Order o, Item i " +
"WHERE (o.quantity > 25) AND (o.item = i.id)",
"OrderItemResults");
預先定義、可重複使用的查詢,支援 JPQL 與原生 SQL 兩種形式。
命名查詢的核心優勢在於「外部化」——將查詢邏輯與業務代碼分離,便於優化、維護與跨模組複用。但當定義為註解時:
@Entity
@Table(name="ORDER")
@NamedQuery(
name="getAllOrder",
queryString="SELECT OBJECT(o) FROM CustomerOrder as o WHERE o.customerId = :customerId")
public class CustomerOrder implements Serializable { ... }
問題在於:
這本質上違背了 ORM「抽象資料庫細節」的設計初衷。
JPA 規範完整支援 orm.xml 等 XML 映射檔,且具備關鍵優勢:
queries.xml,實現真正的外部化<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="https://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd">
<named-native-query name="OrderItemResults"
query="SELECT o.id, o.quantity, o.item, i.id, i.name, i.description
FROM Order o, Item i
WHERE (o.quantity > 25) AND (o.item = i.id)"
result-set-mapping="OrderItemMapping" />
<sql-result-set-mapping name="OrderItemMapping">
<entity-result entity-class="com.acme.Order">
<field-result name="id" column="id"/>
<field-result name="quantity" column="quantity"/>
<field-result name="item" column="item"/>
</entity-result>
<entity-result entity-class="com.acme.Item">
<field-result name="id" column="id_1"/>
<field-result name="name" column="name"/>
<field-result name="description" column="description"/>
</entity-result>
</sql-result-set-mapping>
</entity-mappings>
命名查詢只是冰山一角。過度依賴註解映射會導致:
JPA 專家組雖在規範中保留 XML 映射,但文檔範例幾乎全為註解,誤導社群以為註解是「首選」。實則上,XML 映射才是企業級應用的正統選擇。
META-INF/orm.xml 或自定義映射檔SqlResultSetMapping 映射回領域物件@Entity、@Table、@Column 等結構性元數據回歸 JPA 設計初衷:讓 Java 代碼專注領域建模,將資料庫細節外部化至 XML,才能真正發揮 ORM 的抽象價值。