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

来源:互联网 发布:58电话号码采集软件 编辑:程序博客网 时间:2024/05/21 09:00

Java代码

Configuration cfg = new Configuration().configure();   
 SessionFactory sf = cfg.buildSessionFactory();   
 Session session = sf.openSession();    
Transaction tr = session.beginTransaction();    
Configuration cfg = new Configuration().configure(); 
SessionFactory sf = cfg.buildSessionFactory(); 
Session session = sf.openSession(); 
Transaction tr = session.beginTransaction();Java代码  
Pet pet = (Pet) session.load(Pet.class, 3);         
Pet pet = (Pet) session.load(Pet.class, 3);  
/**load:
* 控制台并没有打印任何select信息
* 1:返回的是代理对象 ,没有真正的访问数据库
* 2:如果对象不存在访问其属性则抛出:ObjectNotFoundException异常
* 3: pet.getPetName();现在访问pet对象的属性,这样才真正的访问数据库,
*/

Java代码


Configuration cfg = new Configuration().configure();   
 SessionFactory sf = cfg.buildSessionFactory();    
Session session = sf.openSession();    
Transaction tr = session.beginTransaction();   
 Configuration cfg = new Configuration().configure();
 SessionFactory sf = cfg.buildSessionFactory(); 
Session session = sf.openSession();
 Transaction tr = session.beginTransaction();Java代码 
 Pet pet = (Pet) session.get(Pet.class, 3);   
 Pet pet = (Pet) session.get(Pet.class, 3);    
/** get:     * 控制台有select语句    
* 1:用get() 总是会和数据库交互    
* 2: pet.getPetName()    
* 如果此对象不存在访问其属性则抛出:java.lang.NullPointerException 异常   
 */ 效率上肯定是load 更高

 

 

Hibernate中Session.load/get方法均可以根据指定的实体类和id从数据库读取记录,并返回与之对应的实体对象。其区别在于:

1.get()方法直接返回实体类,load()方法可以返回实体的代理类实例。

2.hibernate load是采用延迟机制(当lazy属性为true时)而hubernate 个头不采用延迟机制(get语句马上读库)

3.找不到符合条件的数据 get方法将返回nullload将会报出ObjectNotFoundExcepion

延迟加载:Hibernate尽量延迟向数据库发送sql,它自己有一个缓冲区,先把sql放在里面,最后一起发送,减少网络开销和数据库开销。

load方法原理:

当对象.hbm.xml配置文件元素的lazy属性设置为true时,调用load()方法时则返回持久对象的代理类实例,此时的代理类实例是由运行时动态生成的类,该代理类实例包括原目标对象的所有属性和方法,该代理类实例的属性除了ID不为null外,所在属性为null值,查看日志并没有HibernateSQL输出,说明没有执行查询操作,当代理类实例通过getXXX()方法获取属性值时,Hiberante才真正执行数据库查询操作。

注意:StudentEhs=(StudentEh)session.load(StudentEh.class,10);System.out.println(s.getId());

这两条语句同样不会产生sql语句,因为session.load后会在hibernate的一级缓存里存放一个map对象,该map的key就是id的值,但是当你getId()时,它是从一级缓存里取map的key值,而不去执行数据库查询。

当对象.hbm.xml配置文件元素的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。

自己在开发过程中遇到的问题:

我们用MyEclipsehibernate工具通过数据库生成的DAO类,它的findById方法是用的session.get()方法,这是即时获得pojo对象,如果是load方法,在执行完load后如果关闭了session,那在接下来用到这个pojo对象时就会报session已关闭的错误。

0 0