在使用 Hibernate 執行 HQL 聚合查詢時,開發者常因慣性思維假設返回結構一致,導致運行時拋出 ClassCastException。本文通過一個真實案例,深入剖析單字段與多字段聚合查詢在返回類型上的本質差異。
T_SOME_TABLE {
crowid varchar(36);
zrmb float(7,3);
zjdw float(7,3);
}
// 後台 HQL
String hqlStr = "select SUM(t.zrmb) AS SUM_1, SUM(t.zjdw) AS SUM_2 from T_SOME_TABLE t where 1=1";
List sumList = baseDao.find(hqlStr); // 返回 List<Object[]>
// 前台遍歷
ArrayList sumList = (ArrayList) request.getAttribute("sumList");
if (sumList != null) {
for (int i = 0; i < sumList.size(); i++) {
Object[] tempObj = (Object[]) sumList.get(i); // 強轉 Object[]
sum1 = tempObj[0] == null ? "0.0" : tempObj[0].toString();
sum2 = tempObj[1] == null ? "0.0" : tempObj[1].toString();
}
}
// 後台 HQL - 僅查詢一個聚合字段
String hqlStr = "select SUM(t.zrmb) AS SUM_1 from T_SOME_TABLE t where 1=1";
List sumList = baseDao.find(hqlStr); // 實際返回 List<Object> 而非 List<Object[]>
// 前台仍按 Object[] 處理 → ClassCastException
Object[] tempObj = (Object[]) sumList.get(i); // 這裡報錯!
Hibernate 內部優化機制:
Object[] 數組,List<Object[]>Double, Long 等),List<Object>這種差異導致前台統一按 Object[] 處理時,單字段情況下發生類型轉換失敗。
// 單字段聚合正確遍歷
if (sumList != null) {
for (int i = 0; i < sumList.size(); i++) {
Object tempObj = sumList.get(i); // 直接取 Object
sum1 = tempObj == null ? "0.0" : tempObj.toString();
}
}
Map<String, Object> 或 DTO,屏蔽底層差異instanceof 判斷類型後再轉換Hibernate 的這一行為雖然符合直覺(單值無需數組包裹),但極易被慣性思維忽略。理解其內部封裝邏輯,並在架構層面統一數據傳輸格式,是避免此類低級錯誤的關鍵。