`
weitao1026
  • 浏览: 1053673 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

hibernate的延时加载的get和load的区别

阅读更多
在hibernate中我们知道如果要从数据库中得到一个对象,通常有两种方式,一种是通过session.get()方法,另一种就是通过session.load()方法,然后其实这两种方法在获得一个实体对象时是有区别的,在查询性能上两者是不同的。

一.load加载方式

当使用load方法来得到一个对象时,此时hibernate会使用延迟加载的机制来加载这个对象,即:当我们使用session.load()方法来加载一个对象时,此时并不会发出sql语句,当前得到的这个对象其实是一个代理对象,这个代理对象只保存了实体对象的id值,只有当我们要使用这个对象,得到其它属性时,这个时候才会发出sql语句,从数据库中去查询我们的对象。


Java代码  收藏代码

    session = HibernateUtil.openSession(); 
               /*
                * 通过load的方式加载对象时,会使用延迟加载机制,此时并不会发出sql语句,只有当我们需要使用的时候才会从数据库中去查询
                */ 
               User user = (User)session.load(User.class, 2); 

我们看到,如果我们仅仅是通过load来加载我们的User对象,此时从控制台我们会发现并不会从数据库中查询出该对象,即并不会发出sql语句,但如果我们要使用该对象时:




Java代码  收藏代码

    session = HibernateUtil.openSession(); 
          User user = (User)session.load(User.class, 2); 
          System.out.println(user); 

此时我们看到控制台会发出了sql查询语句,会将该对象从数据库中查询出来:




Sql代码  收藏代码

    Hibernate: select user0_.id as id0_0_, user0_.username as username0_0_, user0_.password as password0_0_, user0_.born as born0_0_ from user user0_ where user0_.id=? 

这个时候我们可能会想,那么既然调用load方法时,并不会发出sql语句去从数据库中查出该对象,那么这个User对象到底是个什么对象呢?



其实这个User对象是我们的一个代理对象,这个代理对象仅仅保存了id这个属性:


Java代码  收藏代码

    session = HibernateUtil.openSession(); 
                /*
                 * 通过load的方式加载对象时,会使用延迟加载机制,此时得到的User对象其实是一个
                 * 代理对象,该代理对象里面仅仅只有id这个属性
                 */ 
                User user = (User)session.load(User.class, 2); 
                System.out.println(user.getId()); 

控制台输出:2



我们看到,如果我们只打印出这个user对象的id值时,此时控制台会打印出该id值,但是同样不会发出sql语句去从数据库中去查询。这就印证了我们的这个user对象仅仅是一个保存了id的代理对象,但如果我需要打印出user对象的其他属性值时,这个时候会不会发出sql语句呢?答案是肯定的:


Java代码  收藏代码

    session = HibernateUtil.openSession(); 
               /*
                * 通过load的方式加载对象时,会使用延迟加载机制,此时得到的User对象其实是一个
                * 代理对象,该代理对象里面仅仅只有id这个属性
                */ 
               User user = (User)session.load(User.class, 2); 
               System.out.println(user.getId()); 
               // 如果此时要得到user其他属性,则会从数据库中查询 
               System.out.println(user.getUsername());           

控制台的输出:




Java代码  收藏代码

    2 
    Hibernate: select user0_.id as id0_0_, user0_.username as username0_0_, user0_.password as password0_0_, user0_.born as born0_0_ from user user0_ where user0_.id=? 
    aaa 

相信通过上述的几个例子,大家应该很好的了解了load的这种加载对象的方式了吧。



二、get加载方式

相对于load的延迟加载方式,get就直接的多,当我们使用session.get()方法来得到一个对象时,不管我们使不使用这个对象,此时都会发出sql语句去从数据库中查询出来。

三、使用get和load时的一些小问题

当了解了load和get的加载机制以后,我们此时来看看这两种方式会出现的一些小问题:

①如果使用get方式来加载对象,当我们试图得到一个id不存在的对象时,会返回NULL,此时会报NullPointException的异常







②如果使用load方式来加载对象,当我们试图得到一个id不存在的对象时,此时会报ObjectNotFoundException异常:



为什么使用load的方式和get的方式来得到一个不存在的对象报的异常不同呢??其原因还是因为load的延迟加载机制,使用load时,此时的user对象是一个代理对象,仅仅保存了当前的这个id值,当我们试图得到该对象的username属性时,这个属性其实是不存在的,所以就会报出ObjectNotFoundException这个异常了。

③org.hibernate.LazyInitializationException异常

接下来我们再来看一个例子:


Java代码  收藏代码

    public class UserDAO 
    { 
        public User loadUser(int id) 
        { 
            Session session = null; 
            Transaction tx = null; 
            User user =  null; 
            try 
            { 
                session = HibernateUtil.openSession(); 
                tx = session.beginTransaction(); 
                user = (User)session.load(User.class, 1); 
                tx.commit(); 
            } 
            catch (Exception e) 
            { 
                e.printStackTrace(); 
                tx.rollback(); 
            } 
            finally 
            { 
                HibernateUtil.close(session); 
            } 
            return user; 
        } 
    } 




Java代码  收藏代码

    @Test 
        public void testLazy06() 
        { 
            UserDAO userDAO = new UserDAO(); 
            User user = userDAO.loadUser(2); 
            System.out.println(user); 
        } 

模拟了一个UserDAO这样的对象,然后我们在测试用例里面来通过load加载一个对象,此时我们发现控制台会报LazyInitializationException异常


Java代码  收藏代码

    org.hibernate.LazyInitializationException: could not initialize proxy - no Session  ............. 

这个异常是什么原因呢??还是因为load的延迟加载机制,当我们通过load()方法来加载一个对象时,此时并没有发出sql语句去从数据库中查询出该对象,当前这个对象仅仅是一个只有id的代理对象,我们还并没有使用该对象,但是此时我们的session已经关闭了,所以当我们在测试用例中使用该对象时就会报LazyInitializationException这个异常了。

所以以后我们只要看到控制台报LazyInitializationException这种异常,就知道是使用了load的方式延迟加载一个对象了,解决这个的方法有两种,一种是将load改成get的方式来得到该对象,另一种是在表示层来开启我们的session和关闭session。
分享到:
评论

相关推荐

    hibernate中get和load方法的区别

    在Java的持久化框架Hibernate中,`get`和`load`方法都是用于从数据库中获取对象,但它们之间存在一些重要的区别。理解这些差异对于优化应用程序的性能和避免潜在问题至关重要。 首先,`get`方法是直接从数据库中...

    hibernate get load区别

    在Hibernate框架中,`get`与`load`方法都是用于从数据库加载实体对象的常用手段。然而,这两种方法在实现细节上有着本质的区别,这些差异主要体现在对缓存的利用、异常处理机制以及是否支持懒加载等方面。 #### `...

    Hibernate的get和load方法的区别

    在Java的持久化框架Hibernate中,`get`和`load`方法都是用于从数据库中获取对象,但它们之间存在一些重要的区别。理解这些差异对于优化应用程序的性能和避免潜在问题至关重要。 首先,让我们来深入了解一下`get`...

    hibernate中get和load的区别共5页.pdf

    标签“hibernate中get和lo”暗示了标签可能被意外截断,但我们可以推断完整标签可能是“hibernate中get和load的区别”。 在实际开发中,选择使用`get`还是`load`取决于具体需求。如果需要立即从数据库中获取对象,...

    Hibernate 延迟加载剖析与代理模式应用

    在Java的持久化框架Hibernate中,延迟加载(Lazy Load)是一项重要的优化策略,其核心目标是提高系统性能,减少内存占用,避免不必要的数据库交互。延迟加载允许我们在需要使用数据时才从数据库中加载,而不是在加载...

    hibernate延迟加载解决

    Hibernate 是一款流行的 Java 持久层框架,它支持多种加载策略,包括即时加载和延迟加载。在本文中,我们将重点讨论后者。 ##### 1. 实体对象的延迟加载 **配置方式:** 要在Hibernate中启用实体对象的延迟加载,...

    hibernate 三种 查询 方式 load与get的区别

    本篇文章将详细解析Hibernate中的三种主要查询方式——HQL(Hibernate Query Language)、Criteria API和Query API,并着重讨论`load()`与`get()`方法的区别。 一、HQL查询 Hibernate Query Language(HQL)是...

    Hibernate查询 load与get的区别及其它查询测试

    - 在进行Hibernate查询测试时,应确保数据库连接配置正确,实体类与表结构对应,并在测试代码中模拟不同场景,如正常加载、延迟加载、不存在的实体等,以全面验证`load`和`get`的行为。 - 对于`query`和`criteria`...

    hibernate 延迟加载.docx

    1. **加载方式**:`load()`采用延迟加载,`get()`则立即加载数据。 2. **异常处理**:`load()`假设数据一定存在,如果数据不存在,会抛出`ObjectNotFoundException`异常;`get()`则会先检查缓存,如果缓存中没有对应...

    Hibernate延迟加载

    Hibernate延迟加载是ORM框架Hibernate中的一个重要特性,它旨在提高应用...但是,过度依赖延迟加载可能会导致N+1查询问题,即在遍历集合时产生大量额外的查询,因此在编写查询时需谨慎平衡延迟加载和性能之间的关系。

    Hibernate中get和load方法的区别以及close(),clear()、evict()等的区别

    首先,让我们关注`get`和`load`的区别: 1. **返回结果对比**: - `load`方法如果找不到对应的记录,会抛出`org.hibernate.ObjectNotFoundException`异常。这是因为`load`方法假设给定的ID肯定在数据库中存在,它...

    session的get与load比较

    在Hibernate中,`Session`接口提供了`get`和`load`两种方法来获取数据库中的实体对象。 1. **get** 方法:尝试从当前Session的缓存中获取指定ID对应的实体对象;如果缓存中不存在,则直接执行SQL查询语句从数据库中...

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

    在Hibernate ORM框架中,获取持久化对象的两种主要方法是`get()`和`load()`。它们都是用来根据主键ID查询数据库中的实体对象,但两者在执行机制和返回结果上有显著的区别。 1. `get()`方法 当调用`session.get()`...

    Hibernate之数据加载方式

    1. **单个对象加载(Single Entity Loading)**:通过`Session.get()`或`Session.load()`方法加载单个对象,前者会立即从数据库中取数据,后者创建代理对象,数据在第一次访问时加载。 2. **集合加载(Collection ...

    Hibernate延迟加载原理与实现方法

    总结,Hibernate的延迟加载是提升性能的关键策略之一,它减少了不必要的数据库交互,但需要注意合理使用和取消延迟加载,避免在已关闭的Session中访问延迟加载的对象导致异常。此外,通过配置不同的抓取策略,可以更...

    Hibernate中Session.get()方法和load()方法的详细比较

    Hibernate中Session.get()方法和load()方法是两个常用的数据访问方法,但它们之间有着本质的区别。 首先,从返回值上看,get()方法直接返回实体类,如果查不到数据则返回null。load()方法则返回一个实体代理对象,...

    Hibernate中load方法与get方法的区别

    在Hibernate框架中,`load()`和`get()`都是用于从数据库中检索对象的方法,但它们在功能和行为上存在显著的差异。理解这些差异对于优化应用程序的性能和处理潜在异常至关重要。 首先,`load()`方法执行延迟加载策略...

    ssh_inte2模板常用方法&延迟加载问题

    1. **显式加载关联对象**:在业务层操作结束前,通过Session的load()或get()方法显式加载需要的关联对象,避免在Session关闭后尝试触发延迟加载。 2. **调整事务边界**:确保在需要使用延迟加载对象的代码段内,...

    Hiernate里get和load的区别

    在Hibernate框架中,`get` 和 `load` 都是用来从数据库中获取对象的方法,但它们之间存在一些关键差异。了解这些差异对于高效地使用Hibernate至关重要。 首先,让我们来看看这两个方法的基本用法: 1. `get` 方法...

Global site tag (gtag.js) - Google Analytics