Doesn't session.get() in hibernate always hit

2019-09-18 05:56发布

问题:

Theoretically, session.get() method is supposed to hit the database always, no matter whether the entity is stored in the cache or not. But whenever I use session.get() or session.load(), both doesn't hit the database second time.

    Session session = factory.openSession();
    tx = session.beginTransaction();
    Customer cust = (Customer)session.get(Customer.class,2);    
    System.out.println(cust.getCid()+","+cust.getFirstName()+","+cust.getLastName()+","+cust.getPhone());                                
    Customer cust2 = (Customer)session.get(Customer.class,2);          
    System.out.println(cust2.getCid()+","+cust2.getFirstName()+","+cust2.getLastName()+","+cust2.getPhone());
    tx.commit();
    session.close();

and this is the output,

Hibernate: select customer0_.cid as cid1_1_0_, customer0_.firstName as firstNam2_1_0_, customer0_.lastName as lastName3_1_0_, customer0_.email as email4_1_0_, customer0_.phone as phone5_1_0_, customer0_.aid as aid6_1_0_ from mycustomers customer0_ where customer0_.cid=?
2,Sam,pp,9799999999
2,Sam,pp,9799999999

Select query is executed only once and next time, it's retrieved from the cache. Same output if I use session.load() method also.

Am I missing something here? Please clarify.

回答1:

Here's what's happening here:

  1. The first query on console

    It will always return a “proxy”. For example if you do session.load(Customer.class, 2), it will return a proxy object. Proxy object just have an identifier value and nothing else. You can imagine it to be somewhat like this.

        customer.id = 2;
        customer.fname = null;
        customer.lname = null;
        customer.address = null;
        //rest all properties are null
    

    It will Hit the database whenever you'll access the properties. In your case you're immediately calling ust.getCid() so it will immediately hit the database to fetch those queries. So the first query that you see in your console will appear for both the cases (i.e., session.get() and session.load())

    Try doing this and see what your console looks like:

        Session session = factory.openSession();
        tx = session.beginTransaction();
        Customer cust = (Customer)session.get(Customer.class,2);    
        //do not call any getter.
    

    You'll see the difference on your console.

     

  2. Why is second query not appearing

    Hibernate Second Level Cache
    You're trying to access the same object that you've accessed previously. Hibernate will then (instead of fetching it from database again) fetch it from second level cache.

    You'll find detailed example of this scenario on this page : Hibernate Second Level Cache. (just see the last example, it's similar to what you're getting)