基本上有可以使用的三種方法,其中一些已經被討論:
- 使用HQL查詢或
CreateCriteria
/ICriteria
查詢; 缺點:它不是實體/ DAL的一部分; 上限:它是靈活的;
- 使用屬性映射與
formula
; 缺點:這並不總是可行或不可能的,如果不小心,性能會降低; 上限:它是您的實體不可分割的一部分;
- 創建單獨的XML HBM映射文件並映射到單獨的(將被創建的)實體; 缺點:它不是基礎實體的一部分; 上傳時間:您只需在需要時調用SP,完全控制映射/額外屬性/擴展,就可以使用部分或抽象類與現有實體結合。
我會在這裏簡單地展示一個選項2和3的例子,我相信選項1已經被其他人在本篇文章早些時候已經充分覆蓋了。
當查詢可以創建爲select語句的子查詢,並且映射表中所有需要的參數都可用時,選項二特別有用。如果表不可變,並且/或者以只讀方式緩存,這也會有所幫助,具體取決於您的存儲過程有多沉重。
<class name="..." table="..." lazy="true" mutable="false>
<cache usage="read-only" />
<id name="Id" column="id" type="int">
<generator class="native" />
</id>
<property name="Latitude" column="Latitude" type="double" not-null="true" />
<property name="Longitude" column="Longitude" type="double" not-null="true" />
<property name="PrijsInstelling"
formula="(dbo.DistanceBetween(@lat1, @lat2, Latitude, Longitude))"
type="double" />
... etc
</class>
如果以上是不可能的,因爲在映射的限制,問題緩存或如果您當前的高速緩存設置檢索一個接一個,而不是被更大的金額,你不能改變這種狀況,你應該考慮一個替代方法例如整個查詢與參數的單獨映射。這是相當接近上述CreateSqlQuery方法,但迫使結果集進行某種類型的(你可以以聲明方式設置每個屬性):
<sql-query flush-mode="never" name="select_Distances">
<return
class="ResultSetEntityClassHere,Your.Namespace"
alias="items"
lock-mode="read" >
<return-property name="Id" column="items_Id" />
<return-property name="Latitude" column="items_Latitude" />
<return-property name="Longitude" column="items_Longitude" />
<return-property name="Distance" column="items_Distance" />
</return>
SELECT
Items.*,
dbo.DistanceBetween(@lat1, @lat2, Latitude, Longitude) AS Distance
FROM Items
WHERE UserId = :userId
</sql-query>
您可以調用該查詢,如下所示:
List<ResultSetEntityClassHere> distanceList =
yourNHibernateSession.GetNamedQuery("select_Distances")
.SetInt32("userId", currentUserId) /* any params go this way */
.SetCacheable(true) /* it's usually good to cache */
.List<ResultSetEntityClassHere>(); /* must match the class of sql-query HBM */
根據您的需求,您可以選擇一種方法。我個人使用下面的經驗法則來決定使用什麼方法:
- 計算是輕還是可以緩存? 使用
formula
的方法;
- 是否需要將參數發送到SP/SQL? 使用
sql-query
+映射方法;
- 查詢的結構(非常)變量? 通過代碼使用
ICriteria
或HQL方法。
關於數據排序:當您選擇「公式」或「sql-query mapping」方法時,您必須在檢索數據時執行排序。這與通過當前映射檢索數據沒有區別。
更新:在sql-query XML中糾正了可怕的編輯錯誤。
爲什麼不在Linq/Hql/Criteria中創建DistanceBetween方法? – Paco 2009-10-14 19:25:36
Paco - 你能否詳細說明如何做到這一點? – 2009-10-14 20:01:00
只要看看程序中的sql代碼? 我使用這個算法:http://en.wikipedia.org/wiki/Haversine_formula – Paco 2009-10-16 18:50:56