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