一、什么是Hibernate的一级缓存
session将一个对象加入自己的管理范围内,其实也就是把该对象放入自己的一级缓存中。
Hibernate的一级缓存是指Session级别的缓存,
它是一块内存空间,由Hibernate管理,无需干预。
有了一级缓存,应用程序可以减少访问数据库的次数,提高性能。
查询时:首先会使用对象属性的OID值(对应表中的主键)在Hibernate的一级缓存进行查找:
如果找到,则取出返回,不会再查询数据库,
如果没有找到,再到数据库中进行查询操作。然后将查询结果存放到Session一级缓存中。
保存时:例如,session.save(customer);这个语句就是将
customer保存在自己的一级缓存中,等待事务提交后,hibernate才真正的发sql语句,对数据库进行操作。注意:session进行操作的时候,是将对象加入自己的一级缓存,并不是就直接跟数据库打交道了。
测试一级缓存
测试查询时的一级缓存:只执行一次sql语句
public class CacheLevelOneTest {
@Test
public void testCache(){
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
//第1次查询
Customer c1 = session.get(Customer.class, 1L);
System.out.println(c1);
//第2次查询
Customer c2 = session.get(Customer.class,1L);
System.out.println(c2);
tx.commit();
session.close();
}
}
二、Hibernate 的快照机制
这里引用一个文章https://www.cnblogs.com/hlhdidi/p/6139020.html
在一级缓存中会做些什么事情呢?为什么能够知道是发insert、还是update呢?那这里就要提到一个快照的概念了。
1、快照是数据的副本
2、快照的作用:保证数据一致性
Q:为什么持久态对象可以影响数据库?
A:因为 Hibernate 的 Session 内部存在一级缓存和快照机制!
三、一级缓存的管理
1、一级缓存的自动清空
session.close()
以下例子在第三次查询之前关闭了session,因此一级缓存被清空,所以需要重新执行sql语句
@Test
public void testCache(){
Session session = HibernateUtil.openSession();
Transaction transaction = session.beginTransaction();
//查询
Customer customer1 = session.get(Customer.class, 4L);
System.out.println("第一次查询:" + customer1.getName());
Customer customer2 = session.get(Customer.class, 4L);
System.out.println("第二次查询:" + customer2.getName());
transaction.commit();//存入数据库
session.close();
session = HibernateUtil.openSession();
transaction = session.beginTransaction();
Customer customer3 = session.get(Customer.class, 4L);
System.out.println("第三次查询:" + customer2.getName());
transaction.commit();//存入数据库
session.close();
}
2、把对象移出一级缓存的方法:
session.evict(object) : 把一个对象移出一级缓存
session.clear() : 把一级缓存的所有对象移出
复制前面的
testPersistentStatus方法,并作修改
以下测试数据不会被更新:
/**
* 测试清空一级缓存
*/
@Test
public void testClearCacheLevelOne(){
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
//获取到一个持久态对象
Customer customer = new Customer();
customer.setName("老王");
session.save(customer);
//修改customer的数据
customer.setName("汤姆1");
//把customer对象移出一级缓存
session.evict(customer);
//清空一级缓存
//session.clear();
tx.commit();//事务提交时自动执行update方法
session.close();
}