2015-05-05 88 views
1

假設我已經使用session.get與Hibernate的id爲101的Employee對象'e'。現在,我執行了一個HQL查詢,它檢索所有employess(來自Employee e) 。上述操作都是在同一個會話中完成的。將爲使用查詢檢索到的新對象創建新的Employee對象,還是隻會將'e'添加到結果列表中,以便只有一個員工ID爲101的副本。休眠 - 一級緩存和HQL

回答

1

執行時session.get()

1.)查詢將在DB中觸發,以基於identifier 101獲取Employee

2.)該對象將被放入一級緩存或會話級別。

啓動一個查詢,其中(101,Employee)是提取記錄的一部分。

1)hibernate只會在第一時間獲取標識符。

2.)然後查找緩存中的每個標識符(1st Level + 2nd level),如果存在,將從緩存中獲取對象,否則會觸發單獨的查詢來獲取對象。

1

加入Ankur已經提到的內容 - 讓我們看看底下發生了什麼。我使用JPA API,但概念相同,基礎持久性提供程序是Hibernate。

@Entity 
public class TestEntity { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private long id; 

    private String name; 

    //getter/setters 

} 


EntityManager em = emf.createEntityManager(); 
     em.getTransaction().begin(); 
     TestEntity te = em.find(TestEntity.class, new Long(1)); 
     Query query = em 
       .createQuery("select testEntity from TestEntity testEntity where testEntity.id =:id"); 
     query.setParameter("id", new Long(1)); 

     TestEntity te1 = (TestEntity) query.getSingleResult(); 
     em.getTransaction().commit(); 
     em.close(); 

如果啓用調試日誌,你會看到這樣的事情 - 你可以看到,首先休眠企圖從 第一/第二級緩存加載實體,然後觸發的SQL來獲取數據。更有趣的是,在對應於HQL(JPQL)的查詢被觸發後,hibernate不會嘗試創建任何對象,實際上它將返回相同的實例以在其會話中維護單個副本。

10:56:40.292 [main] TRACE o.h.e.i.DefaultLoadEventListener [DefaultLoadEventListener.java:251]- Loading entity: [com.test.TestEntity#1] 
10:56:40.293 [main] TRACE o.h.e.i.DefaultLoadEventListener [DefaultLoadEventListener.java:425]- Attempting to resolve: [com.test.TestEntity#1] 
10:56:40.293 [main] TRACE o.h.e.i.DefaultLoadEventListener [DefaultLoadEventListener.java:463]- Object not resolved in any cache: [com.test.TestEntity#1] 
10:56:40.303 [main] INFO - select testentity0_.id as id1_11_0_, testentity0_.name as name2_11_0_ from test_entity testentity0_ 
where testentity0_.id=1 

10:56:40.318 [main] DEBUG o.h.engine.internal.TwoPhaseLoad [TwoPhaseLoad.java:160]- Resolving associations for [com.test.TestEntity#1] 
10:56:40.321 [main] DEBUG o.h.engine.internal.TwoPhaseLoad [TwoPhaseLoad.java:286]- Done materializing entity [com.test.TestEntity#1] 
10:56:40.573 [main] INFO /* select testEntity from TestEntity testEntity where testEntity.id =:id */ select testentity0_.id 
as id1_11_, testentity0_.name as name2_11_ from test_entity testentity0_ where testentity0_.id=1 

現在讓我們來看看,如果我刪除查找調用會發生什麼 - 這一次使用從HQL查詢返回的數據創建實體

EntityManager em = emf.createEntityManager(); 
     em.getTransaction().begin(); 

     Query query = em 
       .createQuery("select testEntity from TestEntity testEntity where testEntity.id =:id"); 
     query.setParameter("id", new Long(1)); 
     //em.persist(testEntity); 
     TestEntity te1 = (TestEntity) query.getSingleResult(); 
     em.getTransaction().commit(); 
     em.close(); 



11:00:30.159 [main] INFO /* select testEntity from TestEntity testEntity where testEntity.id =:id */ select testentity0_.id 
as id1_11_, testentity0_.name as name2_11_ from test_entity testentity0_ where testentity0_.id=1 

11:00:30.178 [main] DEBUG o.h.engine.internal.TwoPhaseLoad [TwoPhaseLoad.java:160]- Resolving associations for [com.test.TestEntity#1] 
11:00:30.182 [main] DEBUG o.h.engine.internal.TwoPhaseLoad [TwoPhaseLoad.java:286]- Done materializing entity [com.test.TestEntity#1]