一.get与load对照
在hibernate中get和load方法是依据id取得持久化对象的两种方法。但在实际使用的过程中总会把两者混淆,不知道什么情况下使用get好,什么时候使用load方法效率更高。下边具体说一下get和load的不同,有些时候为了对照也会把find加进来。
1.从返回结果上对照:
load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常get方法检索不到的话会返回null
2.从检索运行机制上对照:
get方法和find方法都是直接从数据库中检索 而load方法的运行则比較复杂首先查找session的persistent Context中是 否有缓存。假设有则直接返回 假设没有则推断是否是lazy。假设不是直接訪问数据库检索,查到记录返回。查不到抛出异常 假设是lazy则须要建立代理对象。对象的initialized属性为false。target属性为null 在訪问获得的代理对象的属性时,检索数据库,假设找到记录则把该记录的对象拷贝到代理对象的target上。并将initialized=true,假设找不到就抛出异常。
3.根本差别说明
假设你使用load方法,hibernate觉得该id相应的对象(数据库记录)在数据库中是一定存在的。所以它能够放心的使用,它能够放心的使用代理来延迟载入该对象。在用到对象中的其它属性数据时才查询数据库,可是万一数据库中不存在该记录,那没办法,仅仅能抛异常。所说的load方法抛异常是指在使用 该对象的数据时,数据库中不存在该数据时抛异常,而不是在创建这个对象时。
因为session中的缓存对于hibernate来说是个相当便宜的资源。所以在load时会先查一下session缓存看看该id相应的对象是否存在,不存在则创建代理。
所以假设你知道该id在数据库中一定有相应记录存在就能够使用load方法来实现延迟载入。
对于get方法,hibernate会确认一下该id相应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找。还没有就查数据库,数据库中没有就返回null。
对于load和get方法返回类型:尽管好多书中都这么说:“get()永远仅仅返回实体类”。但实际上这是不对的,get方法假设在 session缓存中找到了该id相应的对象,假设刚好该对象前面是被代理过的。如被load方法使用过,或者被其它关联对象延迟载入过,那么返回的还是 原先的代理对象,而不是实体类对象,假设该代理对象还没有载入实体数据(就是id以外的其它属性数据),那么它会查询二级缓存或者数据库来载入数据,可是 返回的还是代理对象。仅仅只是已经载入了实体数据。
get方法首先查询session缓存,没有的话查询二级缓存。最后查询数据库。反而load方法创建时首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存和数据库。
二.使用情况分析
至于何种情况使用get什么时候使用load。我感觉最本质的还是要看要载入的持久化对象及数据量。
当要载入的对象与其它对象没有复杂的联系时使用get和load没有太大的差别;当要载入的对象和其它对象之间有复杂的关联关系。而且对象之间的关联数量比較大的情况下使用load方法要比get方法效率高。
比方班级和学生两个持久化对象实体,当取得班级信息时也要载入相应班级的全部学生信息。可是假设在程序中我们如今须要的知识班级信息而不须要学生信息。在这样的情况下get方式要等到班级信息连同学生信息都载入完成才干使用,而load方式会首先载入班级信息并保存班级与学生之间的关系,等到真正使用学生信息的时候才会去载入。所以在关系复杂而且数据量大的情况下load方式要明显有优势。
三.简单总结
总之对于get和load的根本差别。一句话,hibernate对于load方法觉得该数据在数据库中一定存在,能够放心的使用代理来延迟载入,假设在使用过程中发现了问题,仅仅能抛异常;而对于get方法,hibernate一定要获取到真实的数据,否则返回null。在实际使用过程中假设分不清使用哪一种,直接使用load方式就可以。