浅谈Hibernate3中对象的加载

来源:互联网 发布:网络教室软件 破解版 编辑:程序博客网 时间:2024/06/06 08:32

加载方式,也就是决定怎样把数据加载到内存。Hibernate作为一个持久化框架,Hibernate中的加载方式,也就是怎样把数据库中的数据加载到内存当中。其实,在Hibernate中,加载类型可以分为两种,一种是加载实体;另外一种是加载实体中的关联实体。加载方式可以分为即使加载(immediately)、延时加载(lazy)和左外连接加载(outer-join),加载方式只是对加载实体中的关联实体起到作用。

加载实体

在Hibernate中,要从数据库中加载一个实体(注意,这里是加载一个实体),那么可以使用Session.load(Class cls, Serializable id)或者Session.get(Class cls, Serializable id)。你肯定有点奇怪,这两个方法参数都是一样的,其实都是一个思维,要取出某一项指定的记录,当然得指出是哪张表,记录在表中的主键是什么。在实体映射文件中,每一个类都会对应着一张表,而主键类型一般是Serializable接口的实现类,因为实现这个接口可以让数据在网络流中传播,也可以固化对象到磁盘上。当你使用上面两个方法来加载实体的时候,需要知道这么一些事实。

Session.load方法

Session本身作为Hibernate的一级缓存,会在加载实体对象的时候,会将对象保存在一级缓存中,此外,还会将对象保存到二级缓存SessionFactory中。当你在使用load方法加载实体时,Hibernate会先去一级缓存中找,当找不到时,再去二级缓存中找,最后实在找不到,那么就去访问数据库。如果数据库存在这个主键记录,那么返回对应的对象的一个代理,这个代理只有你真正需要到该对象时,它才会执行sql语句来查询数据库并返回对象;否则,抛出一个异常。也就是说,在系统中仅仅是使用SessionFactory作为二级缓存,load方法是存在很大的几率可以避免再次去访问数据库,减少IO的频率的。

Session.get方法

get方法就不一样了,它会将对象保存在一级缓存中,如果是当前的二级缓存只是SessionFactory(其实Hibernate的SessionFactory只是一个测试用的简单二级缓存),那么二级缓存中将不会保存对象。同样,get方法也会去寻找一级缓存,一级缓存找不到就去二级缓存中找指定主键的记录,如果找不到,就去访问数据库。如果数据库存在该记录,那么直接返回对应的对象;否则,返回一个null。在这里,由于get方法在仅仅使用SessionFactory时不会在二级缓存中保存对象,get方法在跨Session时是百分之百去访问数据库的,从而造成频繁的IO操作。而具备了第三方支持的二级缓存中(如EhCache,Hibernate3推荐的缓存),get与load方法都会将对象保存到二级缓存中,其实这两者在非跨Session和跨Session方法,其实IO频率都是一样的,而不同之处也就仅在于是返回对象还是返回对象的代理了。

加载实体的关联实体

在加载实体的关联实体中,我们可以选择三种加载方式的任一种:即时加载、延时加载、左外连接加载。

即时加载

顾名思义,也就是在加载该实体的时候,把该实体的关联实体都加载到内存中。打个比方,一个居民有一个身份证,是一种一对一关单向联,那么在加载居民时,把他相关的身份证实体也加载进来。即时加载适用于一对一关联和简单的一对多关联,在关联较多实体时,需要把较多实体都加载进来,需要开销许多时间和空间。

延时加载

延时加载,就是在加载该实体的时候,该实体的关联实体不加载到内存中,而是在程序中调用到该实体的关联实体时(比如说getter方法),再去加载关联的实体。延时加载使用于多对多关联和复杂的一对多关联。使用延时加载固然可以减少一些时间和空间上的额外开销,但是又会引来新的问题-延时初始化异常。因为在加载实体时,实体的关联关系是由Session来维护的,如果Session关闭了,那么在访问实体的关联实体时,就会抛出延时初始化异常了。要解决这个方法,目前我知道的方案是只延长Session生命周期。

左外连接加载

这种加载方式,其实就是通过数据库的外连接方法来进行实体和关联实体加载,它一次性就把实体及关联实体加载到内存中。左外连接加载方式适用于一对一关联和一对多关联,它需要数据库有比较好的关联性能。

0 0