Hibernate之load和get的区别

Posted 低调的洋仔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate之load和get的区别相关的知识,希望对你有一定的参考价值。

load和get都会可以起到从数据库中获取持久态数据的作用,但是还有些稍微的区别的。


参考下面的这个例子:

@Test(expected = IllegalArgumentException.class)
public void testLazyLoad() throws Exception {
    // 启动
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();

    User user = (User)session.load(User.class, 100L);  // 不存在的ID

    try {
        user.getName();
    } catch (ObjectNotFoundException ex) {
        // 命中数据库发现没有对象即抛出ObjectNotFoundException异常
        throw new IllegalArgumentException("随便抛出一个不可能的异常");
    }

    tx.commit();
    session.close();
}


@Test(expected = IllegalArgumentException.class)
public void testLazyLoad() throws Exception {
    // 启动
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();

    User user = (User)session.load(User.class, 100L);  // 不存在的ID

    Assert.assertTrue(user instanceof HibernateProxy);

    user.getId();  // 由于ID是不被延迟加载的属性,因此不会抛出异常

    try {
        Hibernate.initialize(user);  // 触发命中数据库
        //user.getName();
    } catch (ObjectNotFoundException ex) {
        // 命中数据库发现没有这个对象抛出ObjectNotFoundException异常
        throw new IllegalArgumentException("异常");
    }

    tx.commit();
    session.close();
}
1. 在这里可以看出load并没有直接获取数据,而是获取到的代理对象-->HibernateProxy,如果不获取简单类型的属性的时候是不会抛出异常的,但是get不一样,他直接去数据库中取,他得到的是对象本身,如果得不到的话就会返回空值。


再看一个例子:

@Test
public void testGetAndLoadSession() throws Exception {
    // 启动
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();

    // load在缓存为空的情况下是否会使得加载的对象过一级缓存
    User user1 = (User)session.load(User.class, 1L);  // 存在的ID,此时虽然没有解开Proxy但已经进入缓存
    Assert.assertTrue(user1 instanceof HibernateProxy);
    Hibernate.initialize(user1);  // 解开Proxy,会触发命中数据库操作
    User user3 = (User)session.get(User.class, 1L);
    Assert.assertTrue(user3 instanceof HibernateProxy);  // 即使使用get,但由于缓存中存储的是一个Proxy,所以这里得到的也是Proxy
    Hibernate.initialize(user3);  // 解开Proxy,但不会命中数据库

    // 验证在load一个不存在的ID后,不解开然后get
    User user4 = (User)session.load(User.class, 100L);  // 不存在的ID,仍然将Proxy进入缓存
    Assert.assertTrue(user4 instanceof HibernateProxy);
    //Hibernate.initialize(user3);  // 不解开Proxy
    try {
        session.get(User.class, 100L);  // 得到Proxy,命中数据库尝试解开Proxy,由于ID不存在因此抛出异常
        Assert.fail("ID不存在所以会出错,不会执行本条");
    } catch (ObjectNotFoundException ex) {

    }

    // 清空缓存
    session.clear();

    // 验证缓存为空的情况下get是否为Proxy
    User user6 = (User)session.get(User.class, 1L);  // 命中数据库,直接将组装完成的User实体进入缓存
    Assert.assertTrue(!(user6 instanceof HibernateProxy));

    // 验证get从缓存中取出对象
    User user7 = (User)session.get(User.class, 1L);
    Assert.assertTrue(!(user7 instanceof HibernateProxy)); // 缓存中是真实的User对象,get取出的就是真实的User对象

    // 验证load是否从一级缓存取数据
    User user8 = (User)session.load(User.class, 1L);
    Assert.assertTrue(!(user8 instanceof HibernateProxy));  // 缓存中是真实的User对象,load取出的也是真实的User对象

    tx.commit();
    session.close();
}

2. 如果是load方法将对象加载到了缓存当中,那么在get和load的时候得到的都是代理对象,但是如果是get方法将对象加载到了缓存中的时候,那么在get和load的时候得到的是一个实体对象。


以上是关于Hibernate之load和get的区别的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate中Session之get和load方法的真正区别

Hibernate 关于load和get方法区别

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

Hibernate get 和load的区别

hibernate延迟加载(get和load的区别)

Hibernate中使用load和get加载的区别