2008年7月29日 星期二

JPA 應用實例 <3> @NamedQuery

JPA @NamedQuery 查詢範例

在之前的實例中,我們知道採用HQL語法執行查詢的一般用法如下:

public ProductItem findProductItemBySku(String sku) {
String hql = "from ProductItem where sku=:sku ";
// 取得 EntityManager
EntityManager em = entityManagerFactory.createEntityManager();
Query query = em.createQuery(hql); // 建立查詢語法
query.setParameter("sku", sku); // 填入查詢條件
// 依照產品編號 (SKU) 找到對應的產品基本資料
ProductItem result = (ProductItem) query.getSingleResult();
return result;
}

Hql 查詢語句分別寫在不同 method 的作法是常見也容易理解的,基本上也沒有甚麼大問題,但hql 語法分散在各個不同的方法裡容易造成維護上的困難,尤其是 BO 屬性被更動過的時候,開發者調整了 BO 的屬性也需要同步調整對應的 hql 語法,如果沒有同步調整就容易發生疏漏,沒被同步修正的部分就可能會發生狀況。

關於這個問題,一般的解決方案會把hql 查詢語句從 method 層級提升到 class層級去宣告,如此一來,日後要修改時,只要修正物件層級的變數即可,如此便可減少這類的問題發生;

更好的作法是,採用JPA提供的 @NamedQuery annotation去宣告 hql 查詢語句,在 BO 當中宣告hql 查詢語句,日後如果要調整 BO 當中的屬性宣告時,開發人員僅需調整該 BO 的屬性與hql 查詢語句即可,完全不需要調閱其他的程式碼,就可以完成調整動作,因此,可以有效降地維護成本。

@NamedQuery annotation宣告方式與應用範例如下:

// 宣告 @NameQuery 的範例程式
@NamedQuery(name="findProductItemBySku", query="from ProductItem where sku=:sku ")
@Entity
public class ProductItem {

}

// 引用 @NameQuery 的範例程式
public ProductItem findProductItemBySku(String sku) {
ProductItem result = null;
// 取得 EntityManager
EntityManager em = entityManagerFactory.createEntityManager();
try {
// 依照產品編號 (SKU) 找到對應的產品基本資料
result = (ProductItem) em.createNamedQuery("findProductItemBySku").setParameter("sku", sku).getSingleResult();
} catch (NoResultException err) {
} finally {
em.close();
}
return result;
}

果開發者要在同一個 BO 當中宣告多組 @NameQuery 時,請利用@NamedQueries annotation 加以宣告,範例如下:

// 宣告多組 @NameQuery 的範例程式
@NamedQueries({
@NamedQuery(name="findProductItemBySku", query="from ProductItem where sku=:sku "),
@NamedQuery(name="findProductItemByName", query="from ProductItem where name=:name ")
})
@Entity
public class ProductItem {

}


相關資訊:Java Persistence API

沒有留言: