Hibernate 的延迟加载(懒加载)简介2

初识懒加载
  • 懒加载是指程序推迟访问数据库,这样做可以保证有时候不必要的访问数据库,因为访问一次数据库是比较耗时的。

* Load()方法的懒加载*
  • 如果在session关闭之前都没有对数据库进行访问或进行对所load的对象进行初始化即:Hibernate. initialize(employeeSet) ,则肯定会报错。因为在为访问数据库之前load()方法懒加载返回的是一个对象的代理,获取它的属性都是获取不到的。但是,如果在session关闭之前访问了数据库或对load的对象进行了初始化,则会强行访问一次数据库进行查询并将真正的对象赋值给代理.

one-to-one(元素)懒加载
  • 此种元素的懒加载使用比较少,因为它对性能的增加表现不明显,因此Hibernate对查询主对象的”一对一”懒加载默认是关闭的。
  • 只有基于外键关联方式的“一对一”才能用懒加载。
  • 实现此种懒加载必须在从对象这边同时满足三个条件:
    • ①lazy!=false(lazy的属性有三个选项分别为:no-proxy、false和proxy;
    • ② Constrained = true ;
    • ③ fetch=select。
注意:
  • 主表不能有constrained=true,所以主表没有懒加载。

  • 不在session关闭之前查询IdCard的属性会报错,但getId()和getClass()除外。

  • 在Person和IdCard“一对一”关联关系中通过知道IdCard的id查对应的IdCard时候,Hibernate只会查IdCard相关的信息(不包括IdCard中person信息),只有在代码中执行像cardId.getPerson()这样访问IdCard里面的属性时候才会查询数据库查其中person相关信息。
  • 因为仅仅是“一对一”关联,即使不用懒加载只不过仅仅多查了一条数据而已,所以性能上看不出有什么大的提高。
举例:
Person的映射文件保持不变
<hibernate-mapping package="cn.itcast.domain">
  <class name="Person">
    <id name="id">
      <generator class="native"/>
    </id>
    <property name="name"/>
    <one-to-one name="idCard"/>
  </class>
</hibernate-mapping>
修改IdCard映射文件
<hibernate-mapping package="cn.itcast.domain">
  <class name="IdCard" table="id_card">
    <id name="id">  
      <generator class="foreign">
        <param name="property">person</param>
      </generator>
    </id>
    <property name="usefulLife" column="userful_life"/>
    <one-to-one name="person" constrained="true" lazy="proxy" fetch="select"/>
  </class>
</hibernate-mapping>
注意:
  • lazy=”proxy”和fetch=”select”在这里是可以不用写明的,因为Hibernate默认lazy=”proxy” fetch=”select”

  • lazy的选项proxy表示什么时候加载信息,即:通过代理方式需要加载时候才加载而不是不管需不需要全都加载)

  • fetch的选项select表示通过select方式查询需要的信息

  • 选项join表示通过执行内连接把所有信息统统查出来


One-to-many(元素)懒加载
  • 这种关联关系执行懒加载对程序执行效率是非常有效的。如果不使用懒加载,在论坛中仅仅想查询某贴主时候,则将会一次性将回帖全部查询出来,这不仅浪费时间也是不必要的查询,所以这里使用懒加载时候需要时候才查这是正确的方案。
  • Hibernate默认对one-to-many就是使用的懒加载,但用户也可以取消懒加载操作:
    • 方法一:设置lazy=”false”
    • 方法二:设置fetch=”join”

Many-to-one(元素)懒加载
  • 此关联关系的懒加载和one-to-one的懒加载一样都是可要可不要的,因为对执行效率的提高都不是非常明显。

Many-to-many(元素)懒加载
  • 此关联关系的懒加载和one-to-many的懒加载一样对程序的执行效率的提高都是非常明显的。

Hibernate 默认都是使用懒加载的
  • 如果定义的查询方法 :static Employee query(int id)中没有对
Employee employee =( Employee)session. get(Employee. class, id);

则其中的代理对象idCard没有进行初始化,而在调用此方法时候使用了如下查询操作:

Employee employee =query(1);
System.out.println(employee. getDept(). getName());

这样肯定会出错,因为session关闭前没有初始化Employee。
难道要在static Employee query(int id)中加上Hibernate. initialize(employee)进行代理初始化?
我们知道如果不使用懒加载而在程序中不查employee中的Department对象属性,这样会很浪费资源的。

解决方法一:修改query()方法为:

static Employee query(int id, boolean deptIncluded)
{
  Session session=null;
  Session=HibernateUtil.getSession();
  Employee employee=(Employee)session.get(Employee.class, id);
  If(deptIncluded)
    Hibernate. initialize(employee);
  Return employee;
}

以后调用query()方法是多加一个参数用来指定是否需要初始化代理对象。

解决方法二:使用OpenSessionInView:

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.hibernate.HibernateException;
import cn.itcast.util.HibernateUtil;
public class HibernateSessionUtilFilter implements Filter
{
  protected FilterConfig filterConfig=null;
  public HibernateSessionUtilFilter()
  {

  }
  @Override
       public void destroy()
  {
    this.filterConfig=null;
  }
    @Override
  public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException
  {
    try
    {
      chain.doFilter(request, response);
    }
     finally
     {
       try
       {
         HibernateUtil.commitTransaction();
       }
       catch(HibernateException he)
       {
         HibernateUtil.rollbackTransaction();
       }
       finally
       {
         System.out.println("closeSession已经被执行");
         HibernateUtil.closeSession();
       }
     }
   }
   @Override
   public void init(FilterConfig filterConfig) throws ServletException
   {
     this.filterConfig=filterConfig;
   }
}

最后不要忘记在配置文件中配置此filter。

注意:尽管“Open Session In View”能够解决Hibernate框架的延迟初始化中的Session关闭问题,但也有副作用:如果用户的请求的流程中某一步被阻塞,那在这期间的Session就一直被占用而不能被释放掉。这也导致本次事务访问的事务比较长,这与“对数据库表中的数据访问的事务尽可能短小”的原则相抵触。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值