Hibernate中get() load()的区别

来源:互联网 发布:江本胜水结晶实验 知乎 编辑:程序博客网 时间:2024/06/10 21:45

Hibernate中get()和load()的区别

最近面试中遇到了关于hibernate中get()和load()两个方法的区别,我在论坛看到了各种论述,我总结了他们的观点以及自己的理解来简单说明下,如果有哪里不对的地方欢迎指正。

返回结果

首先要清楚一点的是get()和load()方法都是hibernate中session中获取实体对象两个方法,如果是get()方法加载实体对象,但是如果加载对象失败的话,那么结果会返回为null,而通过load()方式加载实体对象,加载不到的数据话便会抛出ObjectNotFoundException。


执行机制

get( )方法

对于get( )方法,hibernate会确认一下该id对应的数据是否存在,首先会在session一级缓存中查找,如果在session缓存中找到了该id对应的对象;

  • 如果刚好该对象前面是被代理过的,如被load方法使用过,或者被其他关联对象延迟加载过,那么返回的还是原先的代理对象,而不是实体类对象;

  • 如果该代理对象还没有加载实体数据(就是id以外的其他属性数据),那么它会查询二级缓存或者数据库来加载数据,但是返回的还是代理对象,只不过已经加载了实体数据;

  • 如果该id对应的对象并且不是被延迟加载的代理对象,或者在session缓存中没有找到该对象,则查找二级缓存

如果二级缓存中没有的话,就会直接发送sql语句去数据库查询数据返回实体对象,如果数据库中也没有就返回null。

load()方法

对于load方法加载实体对象的时,会根据*.hbm.xml映射文件上类级别的lazy属性的配置(默认为true)选择加载方式;

  • 若为true,则首先在Session缓存中查找,看看该id对应的对象是否存在,不存在则延迟加载,返回实体的代理类对象(该代理类为实体类的子类,由CGLIB动态生成),这个代理对象只保存了实体对象的id值,当我们使用该对象的其他属性值时就会查找二级缓存,二级缓存没有就发出sql语句去数据库查找数据,如果数据库仍没发现符合条件的记录,则会抛出一个ObjectNotFoundException。这也是我们时常所说的延迟加载

  • 若为false,就跟get( )方法加载顺序一样,只是最终若没发现符合条件的记录,则会抛出一个ObjectNotFoundException;


使用get( )和load( )时的注意事项

当我们了解了load和get的加载机制以后,在以后使用过程后需要注意一些问题:

  • 如果使用get方式来加载对象,当我们试图得到一个id不存在的对象时,此时会报NullPointException,这是因为通过get( )方式加载实体对象时候,我们会去数据库中查询出该对象,但是这个id值不存在,所以此时实体对象是null,也就会报NullPointException。

  • 如果使用load方式来加载对象,当我们试图得到一个id不存在的实体对象时,此时会报ObjectNotFoundException,为什么使用load的方式和get的方式来得到一个不存在的对象报的异常不同呢??其原因还是因为load的延迟加载机制,使用load()时,此时的实体对象是一个代理对象,仅仅保存了当前的这个id值,当我们试图得到该对象的其他属性时,这个属性其实是为空,所以就会报ObjectNotFoundException

总结

总之对于get( )和load( )的根本区别,一句话,hibernate对于load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get( )方法,hibernate一定要获取到真实的数据,否则返回null。

原创粉丝点击