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)
发表评论