Hibernate - 一级缓存和HQL

时间:2015-05-05 20:27:10

标签: hibernate

假设我使用带有Hibernate的session.get检索了一个Employee对象'e',其ID为101.现在,我已经执行了一个HQL查询,它检索所有的雇员(来自Employee e)。上述两个操作都在同一会话中完成。是否会为使用查询检索到的对象创建新的Employee对象,或者只是将'e'添加到结果列表中,这样只有一个id为101的员工副本。

2 个答案:

答案 0 :(得分:1)

执行session.get()

1。)将在DB中触发查询,以根据Employee获取identifier 101

2。)对象将被放入第一级缓存或会话级别。

触发查询,其中(101,Employee)是获取记录的一部分。

1。)hibernate将在第一时间获取标识符。

2.)然后查找缓存(1st Level + 2nd level)中的每个标识符,如果存在,将从缓存中获取对象,否则将触发单独的查询以获取对象。

答案 1 :(得分: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();

如果启用调试日志,您会看到类似这样的内容 - 您可以看到第一个Hibernate尝试从中加载实体         第一级/第二级缓存然后触发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 

现在让我们看看如果删除find调用会发生什么 - 这次使用从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]