Hibernate一对一EAGER关联:代码执行结果及原因解析
代码执行结果及详细原因
先直接给出两段打印的结果:
System.out.println(st1.getAdvisor() == st2.getAdvisor());→ 输出trueSystem.out.println(st1 == st3);→ 输出false
下面分别拆解原因:
为什么第一个比较会返回true?
咱们得结合Hibernate的一级缓存和EAGER加载的特性来看:
- 你设置了
Student和Advisor是Fetch.EAGER的一对一关联,这意味着当Hibernate加载Student实例时,会立刻把关联的Advisor也加载进来,而不是等到调用getAdvisor()的时候才懒加载。 - 当你调用
session.load(Student.class, 23)时,Hibernate会把23号学生和他的导师都存入当前Session的一级缓存(也就是会话级别的缓存,只属于这个Session)。 - 紧接着加载25号学生时,Hibernate发现这个学生的导师和23号的是同一个——它会先去一级缓存里查有没有这个导师的实例,查到了就直接复用,不会再去数据库查一遍,也不会新建一个
Advisor对象。 - 所以
st1.getAdvisor()和st2.getAdvisor()指向的是内存里同一个对象,用==比较内存地址自然返回true。
为什么第二个比较会返回false?
这就涉及到Hibernate一级缓存的作用范围了:
- 每个
Session的一级缓存是完全独立的,Session关闭后,缓存里的对象就变成了游离态(不再被Hibernate管理)。 - 第一个Session关闭后,
st1就成了一个普通的Java对象,和Hibernate没关系了。 - 当你打开新的Session并加载23号学生时,Hibernate会在新的Session的一级缓存里创建一个全新的
Student实例(也就是st3),这个对象和之前的st1在内存里是两个不同的实例,地址不一样,所以==比较返回false。
内容的提问来源于stack exchange,提问作者crowley
相关产品推荐
相关产品推荐

