Find()、FindAll() 僅支援單表主鍵查詢與全表掃描。實際專案常需:多表聯結、條件篩選、分頁、聚合統計、模糊查詢等,**HQL (Hibernate Query Language)** 為面向物件的查詢語言,完美解決此類需求。
| SQL | HQL | 說明 |
|---|---|---|
SELECT Name FROM Users | SELECT u.Name FROM Users u | 查詢屬性而非實體 |
SELECT * FROM Users WHERE Name IS NOT NULL | FROM Users u WHERE u.Name IS NOT NULL | 條件過濾 |
SELECT COUNT(*) FROM News | SELECT COUNT(*) FROM News | 聚合函數 |
SELECT * FROM News WHERE Title LIKE '%abc%' | FROM News n WHERE n.Title LIKE ? | 參數化模糊查詢 |
[ActiveRecord("Users")]
public class Users : ActiveRecordBase
{
// ... 主鍵與屬性略 ...
private IList _news;
[HasMany(typeof(News), Table = "News", ColumnKey = "User_Oid")]
public IList News { get => _news; set => _news = value; }
}
[ActiveRecord("News")]
public class News : ActiveRecordBase
{
// ... 主鍵與屬性略 ...
private Users _users;
[BelongsTo("User_Oid")]
public Users Users { get => _users; set => _users = value; }
}
using Castle.ActiveRecord.Queries;
public static IList FindByAuthor(string author)
{
var query = new SimpleQuery(typeof(News), "FROM News n WHERE n.Author = ?", author);
return (IList)ExecuteQuery(query);
}
SimpleQuery 建構子:(Type rootType, string hql, params object[] parameters)ExecuteQuery 回傳 IList,需轉型。public static int RecordCount()
{
var query = new ScalarQuery(typeof(News), "SELECT COUNT(*) FROM News");
return (int)ExecuteQuery(query);
}
public static IList FindByTitle(string title)
{
var query = new SimpleQuery(typeof(News),
"FROM News n WHERE n.Title LIKE ?", "%" + title + "%");
return (IList)ExecuteQuery(query);
}
當 HQL 無法表達極複雜邏輯(如動態組裝 WHERE、存儲過程呼叫),可繼承 ActiveRecordBaseQuery 並實作 Execute(ISession session) 直接操作 NHibernate Session。
SimpleQuery 適用於回傳實體集合的條件查詢;ScalarQuery 適用於 COUNT/SUM/AVG 等單一值。?)防止 SQL Injection 並自動處理型別轉換。Criteria API 或原生 SQL (SQLQuery)。