Prasad
Prasad

Reputation: 90

Hibernate - First Level Caching and HQL

Lets say I have retrieved an Employee object 'e' using session.get with Hibernate whose id is 101. Now, I have executed a HQL query which retrieves all the employess (from Employee e). Both the above operations are done on the same session. Will a new Employee object be created for the one retrieved using the query or will the 'e' just be added to the list of results such that there will be only one copy of employee with id 101.

Upvotes: 1

Views: 930

Answers (2)

Shailendra
Shailendra

Reputation: 9102

Adding to what Ankur has already mentioned - let's see what happens under the hood. I'm using the JPA API's but the concept is same and the underlying persistence provider is 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();

If you enable the debug logs, you would see something like this - as you can see that first Hibernate attempts to load entity from first/second level cache and then fires the SQL to get the data. Even more interesting is that after the query corresponding to HQL(JPQL) is fired hibernate does not attempt to create any object out of it, infact it will return the same instance to maintain a single copy in its session.

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 

Now let' see what happens if I remove the find call - this time the entity is created using the data returned from the HQL query

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]

Upvotes: 1

Ankur Singhal
Ankur Singhal

Reputation: 26077

When executing session.get()

1.) A query will be fired in DB to fetch Employee based on identifier 101.

2.) The object will be put into 1st level cache or session level.

Fire a query, where (101,Employee) is part of fetch records.

1.) hibernate will just fetch the identifiers at the first go.

2.) Then look for each identifier in the cache (1st Level + 2nd level), if present, object will be fetched from cache else a separate query will be fired to fetch the object.

Upvotes: 1

Related Questions