1.hibernate 版本 5.4.21.Final
SQLQuery nativeQuery = entityManager.createNativeQuery(sql).unwrap(SQLQuery.class);
nativeQuery.setResultTransformer(new BeanResultTransformer(cls));
2.代码执行栈
3.org.hibernate.loader.Loader
private List listIgnoreQueryCache(SharedSessionContractImplementor session, QueryParameters queryParameters) {
return this.getResultList(this.doList(session, queryParameters), queryParameters.getResultTransformer());
}
# 其中 this 指向的是 org.hibernate.hql.internal.classic.QueryTranslatorImpl
/**
ResultTransformer resultTransformer 是在查询时指定的
核心:Object result = holderInstantiator.instantiate(row);
*/
protected List getResultList(List results, ResultTransformer resultTransformer) throws QueryException {
HolderInstantiator holderInstantiator = HolderInstantiator.getHolderInstantiator((ResultTransformer)null, resultTransformer, this.getReturnAliasesForTransformer());
if (!holderInstantiator.isRequired()) {
return results;
} else {
for(int i = 0; i < results.size(); ++i) {
Object[] row = (Object[])((Object[])results.get(i));
Object result = holderInstantiator.instantiate(row);
results.set(i, result);
}
return resultTransformer.transformList(results);
}
}
4.调用指定的 ResultTransformer
org.hibernate.hql.internal.HolderInstantiator
// 调用 ResultTransformer 的 transformTuple方法
public Object instantiate(Object[] row) {
return this.transformer == null ? row : this.transformer.transformTuple(row, this.getQueryReturnAliases());
}
5.最后
除了可以自定义 ResultTransformer 外,还有个小技巧
设置数据库方言:
spring.jpa.properties.hibernate.dialect=xxx.MySQL8027Dialect
自定义方言时指定数据类型映射:
// 将 bitint 映射成 long
registerColumnType(Types.BIGINT, StandardBasicTypes.LONG.getName());
registerHibernateType(Types.BIGINT,StandardBasicTypes.LONG.getName());