Hibernate中Sessionload/get方法均可以根据指定的实体类和id从数据库读取记录并返回与之对应的实体对象其区别在于
get()方法直接返回实体类load()方法可以返回实体的代理类实例
hibernate load是采用延迟机制(当lazy属性为true时) 而get不采用延迟机制(get语句马上读库)
找不到符合条件的数据 get方法将返回null
load将会报出ObjectNotFoundExcepion
get支持多态查询load只有在lazy=false的情况下才支持多态查询
所谓多态查询就是可以明确区分加载的是什么类型的对象load采用代理机制无法支持
延迟加载:Hibernate尽量延迟向数据库发送sql它自己有一个缓沖区先把sql放在里面最后一起发送减少网络开销和数据库开销
load方法原理
当对象hbmxml配置文件元素的lazy属性设置为true时调用load()方法时则返回持久对象的代理类实例此时的代理类实例是由运行时动态生成的类该代理类实例包括原目标对象的所有属性和方法该代理类实例的属性除了ID不为null外所在属性为null值查看日志并没有Hibernate SQL输出说明没有执行查询操作当代理类实例通过getXXX()方法获取属性值时Hiberante才真正执行数据库查询操作
注意
StudentEh s=(StudentEh)sessionload(StudentEhclass);
Systemoutprintln(sgetId());
这两条语句同样不会产生sql语句因为sessionload后会在hibernate的一级缓存里存放一个map对象该map的key就是id的值但是当你getId()时它是从一级缓存里取map的key值而不去执行数据库查询
当对象hbmxml配置文件元素的lazy属性设置为false时调用load()方法则是立即执行数据库并直接返回实体类并不返回代理类而调用get()方法时不管lazy为何值都直接返回实体类
get方法原理
get方法hibernate会确认一下该id对应的数据是否存在首先在session缓存中查找然后在二级缓存中查找还没有就查数据库数据库中没有就返回null
get方法如果在session缓存中找到了该id对应的对象如果刚好该对象前面是被代理过的如被load方法使用过或者被其他关联对象延迟加载过那么返回的还是原先的代理对象而不是实体类对象如果该代理对象还没有加载实体数据(就是id以外的其他属性数据)那么它会查询二级缓存或者数据库来加载数据但是返回的还是代理对象只不过已经加载了实体数据
总结描述
如果使用load方法hibernate认为该id对应的对象(数据库记录)在数据库中是一定存在的所以它可以放心的使用代理来延迟加载该对象在用到对象中的其他属性数据时才查询数据库但是万一数据库中不存在该记录那没办法只能抛异常所说的load方法抛异常是指在使用该对象的数据时数据库中不存在该数据时抛异常而不是在创建这个对象时由于session中的缓存对于hibernate来说是个相当廉价的资源所以在load时会先查一下session缓存看看该id对应的对象是否存在不存在则创建代理所以如果你知道该id在数据库中一定有对应记录存在就可以使用load方法来实现延迟加载
而对于get方法hibernate一定要获取到真实的数据否则返回null
自己在开发过程中遇到的问题:
我们用MyEclipse hibernate工具通过数据库生成的DAO类它的findById方法是用的sessionget()方法这是即时获得pojo对象如果是load方法在执行完load后如果关闭了session那在接下来用到这个pojo对象时就会报session已关闭的错误