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

NHibernate實戰(3):HQL 查詢語言基礎與參數化最佳實踐

     編輯:關於.NET

前言

NHibernate 查詢語言 (HQL) 是面向對象的 SQL 方言,支援繼承、多態、關聯導航。本文系統講解五大子句基礎語法與四種參數化寫法,奠定高效查詢基礎。

HQL 核心優勢

  • 操作對象/屬性而非表/欄位:from Customer c select c.Firstname
  • 編譯時語法驗證(工具支援下)
  • 支援繼承多態查詢:from Animal 可返回 Dog/Cat 實例
  • 關聯導航直觀:c.Orders.elements

五大基礎子句詳解

1. FROM 子句

// 簡單查詢所有
public IList<Customer> From()
    => _session.CreateQuery("from Customer").List<Customer>();

// 別名(as 可省略)
public IList<Customer> FromAlias()
    => _session.CreateQuery("from Customer as customer").List<Customer>();

// 多實體產生笛卡爾積
public IList<Object[]> Cartesian()
    => _session.CreateQuery("from Customer c, Order o").List<Object[]>();

2. SELECT 子句

// 單屬性返回類型化列表
public IList<int> Select()
    => _session.CreateQuery("select c.CustomerId from Customer c").List<int>();

// 多屬性返回 Object[] 數組
public IList<object[]> SelectObject()
    => _session.CreateQuery("select c.Firstname, count(c.Firstname) from Customer c group by c.Firstname")
        .List<object[]>();

// 聚合函數
public IList<object[]> AggregateFunction()
    => _session.CreateQuery("select avg(c.CustomerId), sum(c.CustomerId), count(c) from Customer c")
        .List<object[]>();

// DISTINCT 去重
public IList<string> Distinct()
    => _session.CreateQuery("select distinct c.Firstname from Customer c").List<string>();

3. WHERE 子句

public IList<Customer> Where()
    => _session.CreateQuery("from Customer c where c.Firstname = 'YJing'").List<Customer>();

支援運算符:算術(+ - * /)、比較(= >= <= <> != like)、邏輯(and or not)、字符串連接(||)、SQL 函數(upper/lower)、分組括號、in/between/is null、參數綁定(?, :name)、字面量、枚舉常量。

4. ORDER BY 子句

public IList<Customer> Orderby()
    => _session.CreateQuery("from Customer c order by c.Firstname asc, c.Lastname desc").List<Customer>();

5. GROUP BY 子句

public IList<object[]> Groupby()
    => _session.CreateQuery("select c.Firstname, count(c.Firstname) from Customer c group by c.Firstname")
        .List<object[]>();

參數化查詢四種寫法對比

public IList<Customer> GetCustomersByFirstname(string firstname)
{
    // 寫法1:字符串拼接 —— 禁用!SQL 注入風險
    // return _session.CreateQuery("from Customer c where c.Firstname='" + firstname + "'").List<Customer>();
    
    // 寫法2:位置參數 (ADO.NET 風格) —— 參數從 0 開始
    // return _session.CreateQuery("from Customer c where c.Firstname=?")
    //     .SetString(0, firstname).List<Customer>();
    
    // 寫法3:命名參數 —— 推薦!可讀性好、順序無關、可重複使用
    return _session.CreateQuery("from Customer c where c.Firstname=:fn")
        .SetString("fn", firstname).List<Customer>();
    
    // 寫法4:命名參數列表 —— 適用 IN 查詢
    // var names = new[] {"A", "B"}; .SetParameterList("names", names)
}

命名參數優勢總結

  • 不依賴參數在 SQL 中出現順序
  • 同一查詢中可多次引用同一參數
  • 代碼可讀性與維護性最佳
  • 防止 SQL 注入,類型安全

實戰案例

案例一:按姓名查詢

[Test]
public void GetCustomerByFirstnameTest()
{
    var customers = _queryHQL.GetCustomersByFirstname("YJingLee");
    Assert.AreEqual(1, customers.Count);
    foreach (var c in customers)
        Assert.AreEqual("YJingLee", c.Firstname);
}

案例二:ID 範圍查詢

public IList<Customer> GetCustomersWithCustomerIdGreaterThan(int customerId)
    => _session.CreateQuery("from Customer c where c.CustomerId > :cid")
        .SetInt32("cid", customerId).List<Customer>();

結語

HQL 以對象為中心,語法接近 SQL 但更強大。核心實踐原則:

  1. 永遠使用命名參數 (:name)
  2. 善用 distinct 解決關聯查詢重複
  3. 聚合查詢返回 object[] 或 DTO 投影
  4. 大小寫不敏感,但建議關鍵字大寫、屬性駝峰

下篇將介紹 Criteria API 動態查詢構建。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved