Hibernate DetachedCriteria搭配ResultTransformer和投影查询实体列表报500
问题排查思路
- 第一步:抓取完整异常栈
你当前仅在service和controller层打印了业务逻辑阶段的异常,500错误大概率出现在业务逻辑执行完成后,Spring MVC将SearchResult<User>序列化为JSON的阶段。可以在Controller的catch块中打印完整异常堆栈,或者配置全局异常处理器捕获所有异常输出栈信息,优先确认异常的具体类型和触发点。 - 第二步:排查User实体序列化问题
这是该场景下最常见的报错原因,重点检查三个方向:- 实体是否存在懒加载关联属性:如果User类关联了其他实体/集合且配置了懒加载,DAO层查询结束后Session已经关闭,序列化阶段访问懒加载属性会抛出
LazyInitializationException。可以先给懒加载属性加@JsonIgnore注解测试是否恢复正常,后续按需配置Open Session In View或者查询时主动fetch关联属性即可。 - 是否存在双向关联循环引用:如果User和关联的实体互相持有对方的引用,序列化时会触发无限递归导致栈溢出报错,可以给关联属性加
@JsonManagedReference/@JsonBackReference或者@JsonIgnore处理循环问题。 - 实体是否符合序列化要求:检查User类和
SearchResult类是否提供无参构造函数,所有需要序列化的字段是否有public的getter方法。
- 实体是否存在懒加载关联属性:如果User类关联了其他实体/集合且配置了懒加载,DAO层查询结束后Session已经关闭,序列化阶段访问懒加载属性会抛出
- 第三步:检查分页逻辑的空值问题
你当前的代码中,只有pageNumber >= 0 && pageSize > 0的分支才会给result.setResults(users)赋值,其他情况下results属性为null。如果序列化配置了禁止序列化null值,或者前端接口约定要求results必须返回数组而非null,就会触发报错。建议初始化SearchResult时就把results属性赋值为空ArrayList。 - 第四步:排查Hibernate代理对象序列化问题
你用了Criteria.DISTINCT_ROOT_ENTITY,查询返回的User实例可能是Hibernate代理对象,默认的Jackson序列化无法处理Hibernate代理特有的hibernateLazyInitializer、handler属性,会触发序列化异常。可以引入jackson-datatype-hibernate5模块,在Jackson配置中注册Hibernate5Module来适配Hibernate实体的序列化。 - 第五步:检查Criteria查询的属性映射
虽然你说DAO层已经返回了users列表,还是建议确认Criteria中的字段名是否和实体属性名一致:你代码中Restrictions.eq("first_name", firstName)用了数据库列名,而DetachedCriteria默认是用实体属性名匹配的,如果你的User实体属性名是firstName而非first_name,即使查询能返回结果,也可能出现字段值为空的问题,触发后续的序列化校验报错。
内容的提问来源于stack exchange,提问作者adicto.verde
相关产品推荐
相关产品推荐

