zoukankan      html  css  js  c++  java
  • Hibernate中session.get()和session.load()的区别

    实际上,两个方法都是用来从数据库获取对象,只不过实现机制不一样而已。

    1. session.load()

    • 这种方式总是会返回一个代理而不是真正得去查询数据库。 在Hibernate里面,代理是一个依据ID值获取到的对象,该对象的属性还没有初始化,它看起来就是一个临时的虚拟对象而已。
    • 如果load方法没有找到数据,就会抛出ObjectNotFoundException.

    2. session.get()

    • 这种方式总是会去数据库查询数据并返回一个真实的对象,该对象就代表数据库中的一行而非代理。
    • 如果没有找到数据就会返回null.

    性能方面的区别

    由于某些原因,Hibernate会创建一些对象,当你做关联查询的时候,为了维护对象之间的关系,一般来说你会从数据库中拿到一个对象(持久化的实例)并把该对象作为一个引用指向另一个对象。我们来看一个例子来让大家理解什么情况下我们应该使用session.load().

    1. session.get()

    拿一个股票的应用来说,股票跟股票交易之间应该是一对多的关系,当你保存一次股票交易的时候,一般来说我们会写如下的代码:

    Stock stock = (Stock)session.get(Stock.class, new Integer(2));
               StockTransaction stockTransactions = new StockTransaction();
               //set stockTransactions detail
               stockTransactions.setStock(stock);
               session.save(stockTransactions);

    输出:

    Hibernate:
        select ... from mkyong.stock stock0_
        where stock0_.STOCK_ID=?
    Hibernate:
        insert into mkyong.stock_transaction (...)
        values (?, ?, ?, ?, ?, ?)

    用session.get(), Hibernate会查询数据库以获取Stock对象,并把该对象作为一个引用指向StockTransaction对象。然而,保存流程数据的操作是很耗费资源的,如果一个小时内有成千上万次股票交易,你认为有必要每次都去查询数据库,去首先拿到Stock的真实对象然后把StockTransaction保存到数据库中吗?毕竟来说,你只是需要一个Stock的对象来让StockTransaction引用而已。

    2. session.load()

    在上面的应用场景中,session.load()会是一个好的解决方案,让我们来看一个例子:

    Stock stock = (Stock)session.load(Stock.class, new Integer(2));
               StockTransaction stockTransactions = new StockTransaction();
               //set stockTransactions detail
               stockTransactions.setStock(stock);
               session.save(stockTransactions);

    输出:

    Hibernate:
        insert into mkyong.stock_transaction (...)
        values (?, ?, ?, ?, ?, ?)

    使用session.load()方式,Hibernate不会查询数据库(输出的SQL里面没有select语句)来获取Stock对象,这种方式会返回一个Stock的代理对象 - 一个依据给定的ID值得虚假对象。这这种场景中,一个代理对象就足够用来保存股票交易的记录了。

    异常方面的区别

    session.load()

    tock stock = (Stock)session.load(Stock.class, new Integer(100)); //proxy
    
     //initialize proxy, no row for id 100, throw ObjectNotFoundException
    System.out.println(stock.getStockCode());

    oad方法总是会依据给定的ID值来返回一个代理对象,哪怕这个ID值甚至都不存在于数据库。然而,当Hibernate试图从数据库中获取属性来初始化该代理对象的时候,它就会使用select语句来从数据库查询数据,如果没有找到任何数据行,就会抛出ObjectNotFoundException

    org.hibernate.ObjectNotFoundException: No row with the given identifier exists:
    [com.mkyong.common.Stock#100]

    session.get()

    //return null if not found
    Stock stock = (Stock)session.get(Stock.class, new Integer(100));
    System.out.println(stock.getStockCode()); //java.lang.NullPointerException

    与load方法不一样,如果在数据库中没有找到数据,get方法会返回null.

    总结:

    关于这两个方法的选择没有一成不变的解决方案,你必须要首先理解这两种方法的区别和联系,然后才能决定哪种方式更适合你的应用场景。

    1. load方法支持延迟加载而get方法则不会。
    
    2. load方法在没找到数据的时候会抛出ObjectNotFoundException而get方法则会返回空
  • 相关阅读:
    封装异常处理之坑
    30multipart/form-data和application/x-www-form-urlencoded的区别(二)urlencoded之自动deocde
    使用MAT时的Shallow Size和 Retained Size的区别
    当动态代理遇到ioc
    线程池的原理
    synchroned原理与对象头(yet)
    mysql压力测试与qps监控
    一种mysql jvm死锁
    Android Jni变量对照表
    结构体中使用函数指针
  • 原文地址:https://www.cnblogs.com/tanlei-sxs/p/10190014.html
Copyright © 2011-2022 走看看