Hibernate5.2使用AliasToBean转换结果时AssetInfo转Map类转换异常求助
问题成因
该错误的核心是Hibernate的AliasToBeanResultTransformer错误为AssetInfo类加载了面向Map类型的属性访问器PropertyAccessMapImpl,在属性赋值阶段试图将AssetInfo实例强转为Map,最终抛出类型转换异常。常见触发原因如下:
- Hibernate 5.2处理原生SQL查询时,如果没有显式指定返回列的元数据,部分场景下会错误识别结果封装的目标类型,误用
Map类型的属性访问器。 - 项目中存在多个同名
AssetInfo类,代码导入的类与实际期望映射的类不一致。 - 应用中对
Transformers.aliasToBean(AssetInfo.class)返回的Transformer实例做了自定义修改,导致所有复用该实例的查询都出现类型识别错误。
解决方案
方案1(最简便,推荐):显式声明所有返回列的元数据
在设置结果转换器前,通过addScalar方法指定每个返回列的别名和数据类型,强制Hibernate识别正确的属性映射规则:
import org.hibernate.type.StringType; import org.hibernate.type.BigDecimalType; // 业务代码修改为如下 Query<AssetInfo> query = session.createNativeQuery(sql.toString()) .addScalar("assetId", StringType.INSTANCE) .addScalar("caseNumber", StringType.INSTANCE) .addScalar("assetDescription", StringType.INSTANCE) .addScalar("assetValue", BigDecimalType.INSTANCE) .setResultTransformer(Transformers.aliasToBean(AssetInfo.class)); buildParmList(query, searchCriteria); List<AssetInfo> result = query.list();
方案2:使用官方SqlResultSetMapping声明结果映射
如果不想每次查询都写addScalar,可以通过注解声明全局的结果映射规则:
- 给
AssetInfo类添加结果映射注解:
import javax.persistence.SqlResultSetMapping; import javax.persistence.ConstructorResult; import javax.persistence.ColumnResult; @SqlResultSetMapping( name = "AssetInfoMapping", classes = @ConstructorResult( targetClass = AssetInfo.class, columns = { @ColumnResult(name = "assetId", type = String.class), @ColumnResult(name = "caseNumber", type = String.class), @ColumnResult(name = "assetDescription", type = String.class), @ColumnResult(name = "assetValue", type = BigDecimal.class) } ) ) public class AssetInfo { // 原有属性、无参构造、get/set方法保持不变 // 新增对应参数的构造方法 public AssetInfo(String assetId, String caseNumber, String assetDescription, BigDecimal assetValue) { this.assetId = assetId; this.caseNumber = caseNumber; this.assetDescription = assetDescription; this.assetValue = assetValue; } }
- 查询时直接指定映射名称即可,无需再设置ResultTransformer:
Query<AssetInfo> query = session.createNativeQuery(sql.toString(), "AssetInfoMapping"); buildParmList(query, searchCriteria); List<AssetInfo> result = query.list();
方案3:排查类导入和Transformer复用
- 检查代码中导入的
AssetInfo类是否为你期望的目标类,避免导错同名类。 - 避免全局复用同一个
Transformers.aliasToBean实例,每次查询单独生成新的Transformer实例,避免实例被其他逻辑污染。
内容的提问来源于stack exchange,提问作者Entropy
相关产品推荐
相关产品推荐

