You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Grails 5升级后Hibernate返回代理而非实际对象的原因及恢复配置

Grails 3 升级到 5 后类型转换异常原因及解决配置

问题根源

Grails 5 依赖的 Hibernate 版本(5.4+)相比 Grails 3 所用的 Hibernate 5.x 早期版本,调整了懒加载代理的生成机制:

  • Grails 3 中,懒加载实体的代理类会直接继承目标实体(比如Tissue),所以instanceOf(Tissue)判断和强制类型转换都能正常执行。
  • Grails 5 对应的 Hibernate 版本默认采用非继承类的代理实现(基于接口或独立代理类),此时item.product是 Hibernate 动态生成的代理实例,而非Tissue类的直接实例,直接强转就会触发类型转换异常,instanceOf判断也会返回false。

恢复原有行为的配置

如果希望兼容旧代码,可通过修改 Hibernate 配置强制使用基于类的代理:
在application.yml中添加:

hibernate:
  proxy:
    factory_class: org.hibernate.proxy.pojo.bytebuddy.ByteBuddyProxyFactory
  use_class_enhancement: false

若使用application.groovy则配置为:

hibernate {
    proxy.factory_class = 'org.hibernate.proxy.pojo.bytebuddy.ByteBuddyProxyFactory'
    use_class_enhancement = false
}

说明:use_class_enhancement设为false会关闭 Hibernate 的字节码增强功能,虽然能恢复旧代理模式,但可能损失部分懒加载优化特性,需根据业务场景权衡。

更优的适配方案

Hibernate 调整代理逻辑是为了提升框架灵活性,更推荐的长期适配方式是:

  • 保留Hibernate.unproxy(item.product)的用法,获取真实实体实例后再进行类型转换与判断。
  • 或者使用 Grails 提供的GrailsHibernateUtil.unproxy()工具方法,效果一致。
  • 也可以通过Hibernate.getClass()判断真实类型:
if (Hibernate.getClass(item.product) == Tissue) {
    Tissue product = (Tissue) Hibernate.unproxy(item.product)
}

内容的提问来源于stack exchange,提问作者Dylan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 11:46:03