Hibernate:在同一个Session中使用load()和get()选择相同的记录

时间:2014-08-01 13:33:59

标签: java hibernate session proxy

一些网络文章说'load()方法将创建一个与工作单元相关的流程,直到使用流创建真正的持久对象,后来引用变量停止引用代理并开始引用实际obj代表记录'

(表示会话将与两个实例关联以执行加载)。

至于我的理解“load()方法可能会返回一个代理,一个占位符,没有 点击数据库。这样做的结果是,一旦您尝试访问返回的占位符并强制您可能会在以后获得ObjectNotFoundException 它的初始化“。(参考书:Java Persistence With Hibernate)。

这意味着会话将与仅一个实例相关联,该实例是执行加载的代理。

这是一个显示我理解的例子。

    Session mysql_session1 = session_factory.openSession();

    logger.info("calling load()");
    POCEntity1 p = (POCEntity1) mysql_session1.load(POCEntity1.class, 12);
    /*
     * Will create a proxy which doesn't have the real data means will not
     * completely initialized until we invoke methods on it to get data.
     */
    logger.info("calling get()");

    POCEntity1 p1 = (POCEntity1) mysql_session1.get(POCEntity1.class, 12);
    /*
     * Now,the get method will directly hits the database with a select
     * query even though an object(proxy) with same identifier value already
     * associating with the session.Because the session will mark the
     * proxy's status as uninitialized ,so after calling get session will
     * re-writes the state/completes the initialization of the proxy. so p1 also
     * refers the same object.
     */

    logger.info("calling load() again ");
    POCEntity1 p2 = (POCEntity1) mysql_session1.load(POCEntity1.class, 12);

    logger.info("p==p1" + (p == p1)); //p==p1true
    logger.info("p==p2" + (p == p2)); //p==p2true
    logger.info("p1==p2" + (p1 == p2));//p1==p2true

    logger.info("p.getTitle" + p.getTitle()); 
    /*
     * will not making hibernate to generate another select query. 
     * only one select query will be generated.
     */

那么,请让我知道我是否正确理解了概念(关于load(),load()之后的正确与否...

我的例子是这样说的 “get()方法将使用前面的load()方法创建的代理并完成其初始化,而不是返回一个新实例并引用它。(p == p1true)”。

先谢谢!!。

注意:我使用了已分配的生成器。

1 个答案:

答案 0 :(得分:0)

你选择了正确的方法,这些方法的语义有时会造成混乱。以下是两种方法的实际应用:

  • 您可以在必须设置外键关系的情况下使用load,您可以设置对象而不实际加载它。加载仅确保具有该ID的对象存在,这就是您发现它抛出ObjectNotFoundException

    的原因

    Car c = new Car(); Engine e = (Stock)session.load(Engine.class, new Integer(1)); c.setEngine(e); session.save(c);

请注意,您只需要在汽车中设置引擎,而您实际上并不需要引擎的任何属性。

  • 当您确实需要该对象时使用get。

    Engine e = (Stock)session.get(Engine.class, new Integer(1)); System.out.println(e.getYear();

希望这澄清。

另请参阅Whats the advantage of load() vs get() in Hibernate?

Hibernate: Difference between session.get and session.load

干杯!!