当前位置:编程学习 > JAVA >>

Hibernate读书笔记-----懒加载分析

  懒加载是指程序推迟访问数据库,这样做可以保证有时候不必要的访问数据库,因为访问一次数据库是比较耗时的。
         一、load方法的懒加载
         先看如下代码段
[java]
<span style="font-size:16px;">public class UserManager { 
 
    public static void main(String[] args) { 
        Users user = new Users(); 
        user.setBirthday(new Date()); 
         
        Name name = new Name(); 
        name.setFirstName("guo"); 
        name.setLastName("zhao"); 
         
        user.setName(name); 
        addUser(user); 
         
        Users users = getUser(user.getId()); 
        System.out.println(users.getName()); 
         
    } 
     
     
    static Users getUser(int id){ 
        Session session = HibernateUtil.getSession(); 
        try { 
            Users users = (Users) session.load(Users.class, id); 
            return users; 
        } finally{ 
            session.close(); 
        } 
    } 
     
    static void addUser(Users users){ 
        Session session = null; 
        Transaction tx = null; 
         
        try { 
            session = HibernateUtil.getSession(); 
            tx = session.beginTransaction(); 
 
            session.save(users); 
            tx.commit(); 
        } catch (HibernateException e) { 
            if (tx!=null) { 
                tx.rollback(); 
            } 
            throw e; 
        }finally{ 
            if(session!=null){ 
                session.close(); 
            } 
        } 
    } 
}</span> 

         上面代码是先增加一个用户、然后再查询这个用户的name组合属性。运行上面的时候,该程序会抛出这样一个异常:
Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session这就是懒加载不能初始化异常。其原因就在于no session。在前面个持久化对象中已经说明:使用load方法时,该方法将具有延迟加载的功能,load方法并不会立即去访问数据库,它会返回一个代理对象,只有当你真正去访问这个对象的时候,它才会去访问数据库。
         通过上面的图,我们看出,hibernate根本就没有select语句,也就是说hibernate没有去访问数据库,所以这个时候你去访问它肯定是没有的。但为什么没有抛出空指针异常?没有抛出空指针异常,也就是说明User对象是存在的,那它是什么呢?通过输出user.getClass()可以看出是这样一个东西:
         class com.hibernate.domain.Users_$$_javassist_5。
         这个user就是load返回的代理对象。但是这个对象并不是我们所要的。我们所要的是一个User实例对象。
         那么怎么解决这个问题呢?
         第一种方法:在关闭session之前访问该对象
[java] 
<span style="font-size:16px;">    static Users getUser(int id){ 
        Session session = HibernateUtil.getSession(); 
        try { 
            Users users = (Users) session.load(Users.class, id); 
            users.getName(); 
            return users; 
        } finally{ 
            session.close(); 
        } 
    }</span> 
         不过这句话看起来会很奇怪。我们通常会采用如下的方式
[java] 
<span style="font-size:16px;">    static Users getUser(int id){ 
        Session session = HibernateUtil.getSession(); 
        try { 
            Users users = (Users) session.load(Users.class, id); 
            Hibernate.initialize(users); 
            return users; 
        } finally{ 
            session.close(); 
        } 
    }</span> 
         利用hibernate的initialize()方法将这个代理对象给初始化。
         注:在使用代理对象的getId()方法和getClass()方法的时候,并不会抛出不能初始化异常,因为这两个属性并不用查询数据库。
 
         二、在缺省的情况下,hibernate对于关联关系会采用懒加载的方式。也就是说1-1、1-N、N-1、N-N都存在懒加载的问题。
           2.1、one-to-one懒加载
         一对一的懒加载并不常用,因为懒加载的目的是为了减少与数据库的交互,从而提高执行效率,而在一对一关系中,主表中的每一条数据只对应从表的一条数据库,就算都查询也不会增加多少交互的成本,而且主表不能有contrained=true,所以主表是不能懒加载的。但是从表可以有

补充:软件开发 , Java ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,