hibernate中的session.get()是否总是命中数据库?

时间:2017-03-03 05:05:01

标签: java hibernate hql hibernate-cache

理论上,无论实体是否存储在缓存中,session.get()方法都应该始终命中数据库。但每当我使用session.get()或session.load()时,它们都不会第二次访问数据库。

    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();

这是输出,

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

选择查询仅执行一次,下次从缓存中检索。如果我也使用session.load()方法,则输出相同。

我在这里遗漏了什么吗?请澄清。

1 个答案:

答案 0 :(得分:-1)

以下是这里发生的事情:

  1. 控制台上的第一个查询

    它将始终返回“代理”。例如,如果您执行session.load(Customer.class, 2),它将返回代理对象。代理对象只有一个标识符值,没有别的。你可以想象它有点像这样。

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

    只要您访问属性,就会点击数据库。在您的情况下,您立即调用ust.getCid(),以便它立即命中数据库以获取这些查询。因此,您在控制台中看到的第一个查询将针对这两种情况显示(即session.get()session.load()

    尝试这样做,看看你的控制台是什么样的:

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

    您将在控制台上看到不同之处。

  2. 为什么第二个查询未显示

    休眠二级缓存
    您正尝试访问之前访问过的同一对象。然后Hibernate将(而不是再次从数据库中获取)从二级缓存中获取它。

    您可以在此页面上找到此方案的详细示例:Hibernate Second Level Cache。 (只看最后一个例子,它与你得到的相似)