Hibernate 支持使用原生的SQL查詢,使用原生SQL查詢可以利用某些數據庫特性,原生SQL查詢也支持將SQL語句放在配置文件中配置,從而提高程序的解耦,命名SQL查詢還可以用於調用存儲過程。
SQL查詢是通過SQLQuery接口來表示的,SQLQuery接口是Query接口的子接口,完全可以使用Query接口的方法,SQLQuery增加了二個重載方法
- addEntity():將查詢到的記錄與特定的實體關聯
- addScalar():江查詢的記錄關聯標量值
執行SQL的步驟如下:
- 獲取Hibernate Session對象
- 編寫SQL語句
- 創建SQLQuery對象,調用Session的createSQLQuery方法創建
- 調用SQLQuery對象的 addScalar 或者 addEntity 方法將選出的結果與變量值或實體進行關聯
- 如果SQL語句包含參數,則調用Query的setXxx方法為參數賦值
-
調用Query的list、uniqueResult方法返回查詢的結果集
-
標量查詢
如果希望僅僅讓Hibernate選出某個字段的值,則可以使用標量查詢,通過addScalar方法指定返回的字段值,示例如下:
List list = curSession.createSQLQuery("select * FROM OneToMany_One")
.addScalar("Total_Trade_Amt", StandardBasicTypes.LONG)
.list();
-
實體查詢
如果查詢了某個數據表的全部數據列,且該數據表有對應的持久化類映射,可以通過 addEntity 指定持久化類型,將查詢結果轉換為實體,示例如下:
List list = curSession.createSQLQuery("select * FROM OneToMany_One")
.addEntity(OneToManyForOneModel.class)
.list();
-
SQL參數
SQL語句可以使用二種參數定義方式,參數Key和參數索引的方式
-
參數Key方式:在SQL語句中使用":參數名稱"的方式定義參數,並使用 setParameter方法的參數名稱來給參數賦值,並制定參數的類型,示例如下:
List list = curSession.createSQLQuery("select * FROM OneToMany_One WHERE Record_ID = :reocrdId")
.addEntity(OneToManyForOneModel.class)
.setParameter("reocrdId", 1234, StandardBasicTypes.INTEGER)
.list();
-
參數索引方式:在SQL語句中使用"?"來定義參數,並使用setParameter方法的索引重載來給參數賦值,並制定參數的類型,示例如下:
List list = curSession.createSQLQuery("select * FROM OneToMany_One WHERE Record_ID = ?")
.addEntity(OneToManyForOneModel.class)
.setParameter(0, 1234, StandardBasicTypes.INTEGER)
.list();
-
存儲過程
Hibernate 當前僅支持存儲過程返回標量和實體,調用存儲過程還有如下需求注意的地方:
- 建議采用標准SQL92語法,如{?=call functionName(<parameters>)} 或 {call procedureName(<parameters>)},不支持原生的調用語法。
- 調用存儲過程進的查詢無法使用setFirstResult()、setMaxResults()進行分頁
-
定制化SQL,Hibernate 需要保存、更新和刪除持久化實體時,默認通過一套固定的SQL語句來完成這些功能,如果程序需要改變這套默認的SQL語句,就可以使用Hibernate所提供的定制SQL功能,
- 注解 @SQLInsert 定制插入記錄的SQL語句;
- 注解 @SQLUpdate:定制更新記錄的SQL語句;
- 注解 @SQLDelete:定制刪除記錄的SQL語句;
- 注解 @SQLDeleteAll:定制刪除所有記錄的SQL語句;
- 注解@Loader:定制查詢的SQL語句
他們都有二個參數,其參數sql 表示執行的定制SQL語句(存儲過程),參數 callable 表示該語句是否為存儲過程。如果使用存儲過程時,參數的順序很重要,可以將 org.hibernate.persister.entity 日志級別設置為 debug級別,從而允許查看Hibernate所期待的順序,整個級別下,Hibernate將會輸出 create、update和delete實體的靜態SQL。因為Hibernate 會檢查SQL語句是否執行成功,所以應該讓存儲過程能返回該存儲過程影響的記錄行數,Hibernate通常把CUD操作語句的第一個參數注冊為數值型輸出參數,所以應該讓存儲過程的第一個參數記錄該存儲過程所影響的記錄條數(存儲過程沒有測試成功)