延迟加载和获取策略

时间:2013-04-25 08:25:43

标签: java hibernate orm hibernate-mapping

我正在使用Hibernate 3.6
用户是实体类
联系人是实体类
用户有一个<联系人>
这种关系是单向的,并且映射为一对多。
我尝试了以下延迟加载和获取组合。这是我的理解和实际结果的列表

使用session.get(User.class,< some userId>)或session.load(User.class,< some userId>)

  lazy      fetch       result

* true      join        ignores lazy loading
*                       1 select for retrieving the User and his contacts with a left outer join
*           select      1 select for a User record
*                       1 select for all contacts of the user
*           subselect   1 select for a User record
*                       1 select for all contacts of the user
* false     join        1 select for retrieving the User and his contacts with a left outer join
*           select      1 select for a User record
*                       1 select for all contacts of the user
*           subselect   1 select for a User record
*                       1 select for all contacts of the user

使用session.createQuery(来自用户)

   lazy     fetch           result

 * true     join            1 select for all User records
 *                          1 select for each User record to retrieve their contacts
 *                          respect lazy loading
 *                          probable n + 1
 *          select          1 select for all User records
 *                          1 select for each User record to retrieve their contacts
 *                          probable n + 1
 *          subselect       1 select for all User records
 *                          1 sub-select to retrieve all contact records in one go
 * false    join            1 select for all User records
 *                          1 select for each User record to retrieve their contacts
 *                          probable n + 1      
 *          select          1 select for all User records
 *                          1 select for each User record to retrieve their contacts
 *                          probable n + 1
 *          subselect       1 select for all User records
 *                          1 sub-select to retrieve all contact records in one go

以下是我的一些问题:

  1. 我的理解是否正确?
  2. 当lazy = true时使用session.get(),fetch = subselect为什么Hibernate不执行subselect?我想这是因为它绝对没有必要。我对么 ?
  3. 当lazy = false时使用session.get(),fetch = subselect为什么Hibernate不执行subselect?它应该在这里执行一个,但它不会。我想知道为什么 ?
  4. 当lazy = true时使用session.createQuery(),fetch = join为什么Hibernate延迟加载?它早先没有使用session.get()
  5. 执行此操作
  6. 当lazy = false时使用session.createQuery(),fetch = join为什么Hibernate不使用连接?
  7. 提前致谢

1 个答案:

答案 0 :(得分:0)

好的人,经过多次挖掘,我可以得出结论。只是想与大家分享我的战利品。如果有人觉得他们可以添加更多,欢迎你。让我先从一个示例数据集开始。

The user table
--------------------------------------------------
USER_ID     USERNAME
--------------------------------------------------
1           User One
2           User Two
3           User Three

The contact table
-------------------------------------------------------------------------------------------------------------------
CONTACTID   TITLE   FIRSTNAME   LASTNAME        CITY        COUNTRY             EMAIL                       USER_ID
-------------------------------------------------------------------------------------------------------------------
1           Mr.     Clark       Kent        New York        United States       man-of-steel@anywhere.earth     1
2           Mr.     Hank        Ketcham     Manhattan       United States       dennis-mitchell@somewhere.us    2
3           Mr.     Tony        Stark       Malibu          United States       iron-man@anywhere.earth         2
4           Mr.     Bruce       Wayne       Gotham          United States       dark-knight@gotham.us           2

Q2。使用session.get()时lazy = true,fetch = subselect为什么Hibernate不执行subselect?我想这是因为它绝对没有必要。我对么 ?

A2。是的,这里的子选择绝对没有必要。以下是子选择可能的样子

SELECT   
    u.USER_ID AS USER1_1_,   
    u.USERNAME AS USERNAME1_,   
    c.USER_ID AS USER15_1_1_,   
    c.CONTACTID AS CONTACTID1_,   
    c.CONTACTID AS CONTACTID0_0_,   
    c.TITLE AS TITLE0_0_,   
    c.FIRSTNAME AS FIRSTNAME0_0_,   
    c.LASTNAME AS LASTNAME0_0_,   
    c.CITY AS CITY0_0_,   
    c.COUNTRY AS COUNTRY0_0_,   
    c.EMAIL AS EMAIL0_0_,   
    FROM   
        user u,contact c   
    WHERE   
        u.USER_ID = 2  
    AND   
        c.USER_ID IN    
        (   
            SELECT USER_ID FROM user WHERE USER_ID = u.USER_ID   
        )  

我没有看到在此处执行子选择对于简单地执行单独选择联系人记录的当前策略没有任何好处。事实上,子选择可能是不必要的性能消耗。

Q3。使用session.get()时lazy = false,fetch = subselect为什么Hibernate不执行subselect?它应该在这里执行一个,但它不会。我想知道为什么 ?

A3。好。再次,这里是子选择可能是什么样的(与上面的一个具有一些其他id完全相似)

SELECT   
    u.USER_ID AS USER1_1_,   
    u.USERNAME AS USERNAME1_,   
    c.USER_ID AS USER15_1_1_,   
    c.CONTACTID AS CONTACTID1_,   
    c.CONTACTID AS CONTACTID0_0_,   
    c.TITLE AS TITLE0_0_,   
    c.FIRSTNAME AS FIRSTNAME0_0_,   
    c.LASTNAME AS LASTNAME0_0_,   
    c.CITY AS CITY0_0_,   
    c.COUNTRY AS COUNTRY0_0_,   
    c.EMAIL AS EMAIL0_0_,   
    FROM   
        user u,contact c   
    WHERE   
        u.USER_ID = 3  
    AND   
        c.USER_ID IN    
        (   
            SELECT USER_ID FROM user WHERE USER_ID = u.USER_ID   
        )  

正如您所看到的,这不会产生任何记录,因为USER_ID = 3没有任何联系人记录。这违背了为User记录执行session.get()的整个目的,其中get()将返回null,尽管表中有有效的用户记录。因此,单独选择联系人记录是唯一的出路。

Q4。使用session.createQuery()时lazy = true,fetch = join为什么Hibernate延迟加载?先前没有使用session.get()

执行此操作

Q5。使用session.createQuery()时lazy = false,fetch = join为什么Hibernate不使用连接?

答。我目前的理解是,这可能仅仅是因为Hibernate不希望最终触发选择大量数据集(包括所有用户记录及其联系人记录)并在内存中加载大量集合的连接。