Spring5+Hibernate5项目forEach方法出现ClassCastException求助
嘿,我一眼就看出问题所在了——你遇到的java.lang.ClassCastException是因为Hibernate返回的结果和你预期的类型不匹配!
问题根源
当你在HQL里写SELECT id,name,company,address,salary FROM EmployeeHLO...这种指定具体列的查询时,Hibernate不会自动把结果封装成EmployeeHLO实体对象,而是返回**Object[]数组列表**——每个数组里的元素依次对应你查询的每一列值。所以当你在Service层的listHlo.forEach(hlo->{...})里把这些数组当成EmployeeHLO处理时,自然就会抛出类型转换异常。
几种解决办法,按推荐程度排序:
1. 直接查询整个实体(最简洁推荐)
修改你的HQL语句,直接查询EmployeeHLO实体类,而不是单独的列:
// 用别名e指代EmployeeHLO,查询整个实体 private static final String get_Records_By_Range="SELECT e FROM EmployeeHLO e where e.id>=:min and e.id<=:max";
这样Hibernate会自动把查询结果封装成EmployeeHLO对象列表,你后续的Service层代码完全不需要修改就能正常运行。
2. 用addEntity()强制映射到实体(适合需要部分列的场景)
如果你确实只需要查询部分列,但还是想得到EmployeeHLO对象,可以在创建Query时调用addEntity()指定实体类:
@Override public List<EmployeeHLO> getRecordsByIdRange(int start, int end) throws Exception { List<EmployeeHLO> listHlo= null; listHlo= ht.execute(new HibernateCallback<List<EmployeeHLO>>() { @Override public List<EmployeeHLO> doInHibernate(Session ses) throws HibernateException { Query query= ses.createQuery("SELECT e.id,e.name,e.company,e.address,e.salary FROM EmployeeHLO e where e.id>=:min and e.id<=:max") // 告诉Hibernate把结果映射到EmployeeHLO实体 .addEntity(EmployeeHLO.class); query.setInteger("min", start); query.setInteger("max", end); return query.list(); } }); return listHlo; }
3. 构造函数查询(适合自定义对象构造的场景)
给EmployeeHLO添加一个包含所有查询列的构造函数:
public EmployeeHLO(int id, String name, String company, String address, float salary) { this.id = id; this.name = name; this.company = company; this.address = address; this.salary = salary; }
然后修改HQL语句,直接调用这个构造函数创建对象:
// 注意要写全实体类的全限定名 private static final String get_Records_By_Range="SELECT new com.st.domain.EmployeeHLO(e.id,e.name,e.company,e.address,e.salary) FROM EmployeeHLO e where e.id>=:min and e.id<=:max";
这样Hibernate会通过你定义的构造函数生成EmployeeHLO对象,返回的列表类型就正确了。
额外小提示
除非有明确的性能优化需求,否则尽量直接查询整个实体类,这样代码更简洁,也能避免这类类型转换的坑。另外,解决完这个问题后,记得测试BeanUtils.copyProperties是否能正确把EmployeeHLO的属性复制到EmployeeDto里——不过从你的代码看,两者属性一致,应该没问题。
内容的提问来源于stack exchange,提问作者Amal Swain

