在Hibernate開發中,常遇到需執行原生SQL(如複雜報表查詢、存儲過程調用、跨庫關聯)並將結果映射到非持久化實體(Value Object, VO)的場景。本文系統梳理Hibernate提供的多種映射機制,按「依賴程度」從高到低、靈活度從低到高對比講解,助你根據業務複雜度選擇最優方案。
// VO需提供對應參數的構造函數
public class Person {
private Long id;
private String name;
private Long age;
// 全參構造函數
public Person(Long id, String name, Long age, Long phone, String address) {...}
// 部分字段構造函數
public Person(Long id, String name, Long age) {...}
// getter/setter省略
}
HQL查詢:
List<Person> list = session.createQuery(
"select new com.example.Person(id, name, age) from PersonEntity"
).list();
List<Object[]> list = session.createSQLQuery(
"select id, name, phone from person"
)
.addScalar("id", StandardBasicTypes.LONG)
.addScalar("name", StandardBasicTypes.STRING)
.addScalar("phone", StandardBasicTypes.LONG)
.addEntity(PersonEntity.class) // 需存在實體映射
.list();
核心代碼:
List<Person> list = session.createSQLQuery(
"select id as \"id\", name as \"name\", phone as \"phone\" from person"
)
.addScalar("id", StandardBasicTypes.LONG)
.addScalar("name", StandardBasicTypes.STRING)
.addScalar("phone", StandardBasicTypes.LONG)
.setResultTransformer(Transformers.aliasToBean(Person.class))
.list();
關鍵點:
提示:若字段較多,可封裝通用工具方法自動生成別名SQL與Scalar定義,減少樣板代碼。
List<Map<String, Object>> list = session.createSQLQuery(
"select * from person"
)
.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP)
.list();
// 每個Map的key為列別名(或列名),value為字段值
List<List<Object>> list = session.createSQLQuery(
"select id, name, phone from person"
)
.setResultTransformer(Transformers.TO_LIST)
.list();
繼承BasicTransformerAdapter實現transformTuple(Object[] tuple, String[] aliases),可實現:
public class NestedVoTransformer extends BasicTransformerAdapter {
@Override
public Object transformTuple(Object[] tuple, String[] aliases) {
// 自定義組裝邏輯
return buildComplexVo(tuple, aliases);
}
}
| 場景 | 推薦方案 | 核心優勢 | 注意事項 |
|---|---|---|---|
| 簡單HQL查詢,字段固定 | 構造函數注入 | 類型安全、可重構 | 僅限HQL,構造函數爆炸 |
| 原生SQL,存在實體映射 | addScalar + addEntity | 復用實體映射元數據 | 需實體映射,返回類型固定 |
| 原生SQL,純VO/DTO映射 | AliasToBean(首選) | 解耦實體、無構造函數限制 | 別名需與屬性名精確匹配 |
| 動態列、無領域模型、通用導出 | ALIAS_TO_ENTITY_MAP / TO_LIST | 零依賴、極簡 | 語義缺失、易誤用 |
| 複雜巢狀結構、類型轉換邏輯 | 自定義ResultTransformer | 完全可控、可復用 | 開發成本高、需充分測試 |
column as "propertyName"指定小寫別名。