”一天一节“之Hibernate的延迟加载--实体对象的延迟加载
??
实体对象的延迟加载是让实体对象在加载的时候,比如session.load()的时候并不立即进行数据加载,而是当我们调用这个实体对象的某个属性方法时,比如xx.getName()时才去进行数据加载工作,这样只有真正用到的地方才去加载,一定程度上减小了性能的开销。这里我们对性能不做深入的探究,我只要说下hibernate的实体对象实现延迟加载的原理。我们来看下面的两个例子,分别是开启和关闭实体对象的延迟加载操作,方面很简单只需要在相应的实体对象映射文件中的class节点设置lazy=”true”和lazy=”false”:
?
示例代码:
Goods goods = ( Goods )session.load(); ①
goods.getName(); ②
?
? ?当lazy=”false”时,调试以上程序可以看到 很显然goods对象的数据立马就被加载出来了。 ? 当lazy=”true”时,调试以上程序可以看到
?
?
看到了吗,产生的结果完全不一样了,不再是直接加载出一个goods对象了,代替它的是Goods$$EnhancerByCGLIB$$e12dcc71(id=26),这个到底是什么,我们来大胆猜想下,我们看到里面有一个CGLIB,会不会是一个代理对象,对的,这个就是在运行期间针对Goods对象所产生的一个代理对象,这个对象具有Goods的所有属性,另外,它还有它自己的一些属性,比如上面我们看到的target属性,而这个属性的类型恰恰就是Goods。由此我们看到hibernate的实体对象延迟加载的实现原理重点就是这个代理对象,通过在运行期产生一个代理来达到延迟的效果。这里有必要说明下当上面程序执行到①时,它实际上并没有去加载数据,而是去构造了一个像上图一样的代理对象,并且这个代理对象拥有了加载对象的所有属性;当程序执行到②时,我们调用的goods.getName()实际上执行的是这个代理对象的proxyObj.getName(),它会先从target对象中的getName()中寻找,如果有对象则直接返回,如果没有则进行数据加载工作,并将加载出来的数据填充到target对象中。
?
?
????以上就是实体对象实现延迟加载的一个基本原理,其核心就在于CGLIB,在运行期构建一个代理对象以达到延迟加载的效果。