禁用 Hibernate 的代理(proxy),获取其真实对象 / Disable Hibernate Proxy and Retrieve Real Entity Object

Java 的各种框架还是很复杂的,不看文档或者不踩坑,都不知道原来框架还“偷偷地”做了一些别的事情——可能这就是一部分面试题的出处吧😂

踩坑

假设有一个 Model 叫做 Person,存到数据库里,框架用的是 Hibernate。代码中用 personDao.findById() 来从数据库中获取一个 Person 实例。项目中大概就是这么写的。

问题来了:要把这个 Person 实例序列化,之后再反序列化。序列化的时候没发现什么问题,反序列化的时候报错了,告诉我这不是一个 Person,而是一个 Person$HibernateProxy$9cjcxRNr

啥情况,代码明明写的是 Person person = personDao.findById(123); 怎么出来的不是 Person 而是 Person 后面加了一长串东西?

解惑

经过搜索,得知 Hibernate 使用 Proxy 实现延迟加载(Lazy Loading)功能。延迟加载,这个我懂,真正用到时才去查询。

找到的资料还告诉我,被偷偷换成了 proxy 之后,还可能有别的坑:直接访问成员变量可能访问不到、用 IDE 断点调试时的行为和实际运行的行为不一致、instanceOf 的行为可能与预期不一致等。

解决

第一个办法,若不确定它是不是 proxy,可以强行让 Hibernate 给我们转回真正的实例,是就转,不是就原样返回:

Object unproxiedEntity = Hibernate.unproxy(proxy); // 自己再做强制类型转换

第二个办法,通过注解,不让 Hibernate 给这个 Model / Entity Class 做延迟加载:

@Proxy(lazy = false)

相关参考


发表评论