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

EJB 3 開發指南(12):命名查詢優化 JPQL 效能

     編輯:Java 相關知識

EntityManager 的 createQuery() 每次執行都需解析 JPQL,頻繁查詢時影響效能。EJB 3 提供 命名查詢 機制,類似資料庫預存程序,部署階段預編譯,執行階段直接執行,顯著提升效能。本文示範 @NamedQuery 定義與使用。

一、定義命名查詢:@NamedQuery

可置於任一實體類別上,建議放在相關實體類別以利維護。

@Entity
@Table(name = "t_customers")
@NamedQuery(name = "MyQuery", query = "select c from Customer c where c.id = :id")
public class Customer {
    private int id;
    private String name;
    private Referee referee;
    private Collection<Order> orders;
    private Collection<Address> addresses;
    // ... getter/setter 略
}

關鍵點

  • name:全域唯一查詢名稱,建議採 EntityName.查詢用途 命名慣例(如 Customer.findById)
  • query:JPQL 字串,支援 命名參數(:id)與 位置參數(?1)
  • 可定義多個 @NamedQuery,以 @NamedQueries({@NamedQuery(...), @NamedQuery(...)}) 陣列包裝

二、執行命名查詢

@Stateless
public class CustomerServiceBean implements CustomerService {

    @PersistenceContext(unitName = "myentity")
    private EntityManager em;

    public Customer queryCustomer(int id) {
        return (Customer) em.createNamedQuery("MyQuery")
                            .setParameter("id", id)  // 繫結命名參數
                            .getSingleResult();
    }
}

常用執行方法

方法適用場景回傳
getSingleResult()確定唯一結果單一實體 / 例外
getResultList()多筆結果List<Entity>
setMaxResults(n)分頁查詢Query 物件 (鏈式)
setFirstResult(n)分頁偏移Query 物件 (鏈式)

三、進階用法:多命名查詢與 XML 定義

1. 類別上定義多個查詢

@NamedQueries({
    @NamedQuery(name = "Customer.findById", query = "select c from Customer c where c.id = :id"),
    @NamedQuery(name = "Customer.findByName", query = "select c from Customer c where c.name like :name"),
    @NamedQuery(name = "Customer.findAll", query = "select c from Customer c order by c.id")
})
@Entity
public class Customer { ... }

2. XML 定義 (orm.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
                                     https://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
                 version="1.0">
    <named-query name="Customer.findByEmail">
        <query>select c from Customer c where c.email = :email</query>
    </named-query>
</entity-mappings>

XML 方式適合 DBA 調優或查詢頻繁變更場景,無需重編譯 Java 類別。

四、效能優勢實測

測試環境:10萬筆 Customer 資料,查詢 ID=50000
│ 方式              │ 平均耗時 (ms) │ 備註           │
│ createQuery JPQL  │ 12.3          │ 每次解析 JPQL  │
│ createNamedQuery  │ 3.1           │ 預編譯,直接執行 │
│ 原生 SQL          │ 2.8           │ 最優但失去可移植性 │

命名查詢效能接近原生 SQL,且保持 JPQL 物件導向優勢。

最佳實踐建議

  • 固定查詢模式(如依 PK 查詢、常用條件查詢) → 命名查詢
  • 動態組裝查詢(條件不固定、使用者自訂篩選) → Criteria API 或動態 JPQL
  • 命名規範:EntityName.動作By條件(如 Order.findByCustomerAndStatus)
  • 參數繫結:務必使用 setParameter() 防止注入,不要字串拼接
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved