理论上,无论实体是否存储在缓存中,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()方法,则输出相同。
我在这里遗漏了什么吗?请澄清。
答案 0 :(得分:-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.
您将在控制台上看到不同之处。
为什么第二个查询未显示
休眠二级缓存
您正尝试访问之前访问过的同一对象。然后Hibernate将(而不是再次从数据库中获取)从二级缓存中获取它。
您可以在此页面上找到此方案的详细示例:Hibernate Second Level Cache。 (只看最后一个例子,它与你得到的相似)