Hibernate的时间戳缓存区域
时间戳:一个详细到秒的时间点,就是一个时分秒的字符串
时间戳缓存区域存放了对于查询结果相关的表进行插入, 更新或删除操作的时间戳.
Hibernate 通过时间戳缓存区域来判断被缓存的查询结果是否过期,
其运行过程如下: (T1和T2没有规定谁先谁后的,是程序需要操作的)
T1 时刻执行查询操作(就例如一个客户1在客户端进行一次查询), 把查询结果存放在 QueryCache 区域, 记录该区域的时间戳为 T1
T2 时刻对查询结果相关的表进行更新操作(管理员在某个时间对客户查询的表进行了更新操作), Hibernate 把 T2 时刻存放在 UpdateTimestampCache 区域.
T3 时刻执行查询结果前(又有另外一个客户执行了客户1同样的查询语句), 先比较 QueryCache 区域的时间戳(T1)和 UpdateTimestampCache 区域的时间戳(T2),
若 T2 >T1, 那么就丢弃原先存放在 QueryCache 区域的查询结果, 重新到数据库中查询数据, 再把结果存放到 QueryCache 区域;
若 T2 < T1, 直接从 QueryCache 中获得查询结果
这就是时间戳的缓存原理:
所有的二级缓存的查询缓存遵循时间戳缓存策略,对象二级缓存和集合二级缓存不支持此策略,
例如咋们对某个对象进行了二级缓存,但同时又做了对象对应表的更新操作
测试代码如下
@Test public void testHibernateSecondLevelCache(){ Employee employee = (Employee) session.get(Employee.class, 15); System.out.println(employee.getName()); transaction.commit(); session.close(); System.out.println("--------------------------------------"); session = sessionFactory.openSession(); transaction = session.beginTransaction(); Employee employee2=new Employee(); employee2.setEmail("sdkfjsd@qq.com"); employee2.setName("jeremy"); employee2.setSalary(8000F); session.save(employee2); Employee employee3 = (Employee) session.get(Employee.class, 15); System.out.println(employee3.getName()); }
我已经设置了二级缓存了,如果二级缓存没有失效我这里应该是发送了一条select语句和一条insert语句,运行结果也是那样
Hibernate: select employee0_.ID as ID1_1_0_, employee0_.NAME as NAME2_1_0_, employee0_.SALARY as SALARY3_1_0_, employee0_.EMAIL as EMAIL4_1_0_, employee0_.DEPT_ID as DEPT_ID5_1_0_ from GG_EMPLOYEE employee0_ where employee0_.ID=? AA -------------------------------------- Hibernate: insert into GG_EMPLOYEE (NAME, SALARY, EMAIL, DEPT_ID) values (?, ?, ?, ?) AA
也就证明了对象二级缓存不支持时间戳缓存策略。collection也是这样,
而查询缓存就支持这个策略:
代码如下:
@Test
public void testQueryCache(){
Query query = session.createQuery("FROM Employee e where e.id=1");
query.setCacheable(true);
List<Employee> emps = query.list();
System.out.println(emps.size());
System.out.println(emps.iterator().next().getClass());
Employee employee=new Employee();
employee.setEmail("sdkfjsd@qq.com");
employee.setName("jeremy");
employee.setSalary(8000F);
session.save(employee);
emps = query.list();
System.out.println(emps.size());
//Criteria criteria = session.createCriteria(Employee.class);
//criteria.setCacheable(true);
}
运行结果:
Hibernate:
select
employee0_.ID as ID1_1_,
employee0_.NAME as NAME2_1_,
employee0_.SALARY as SALARY3_1_,
employee0_.EMAIL as EMAIL4_1_,
employee0_.DEPT_ID as DEPT_ID5_1_
from
GG_EMPLOYEE employee0_
where
employee0_.ID=10
1
class com.atguigu.hibernate.entities.Employee
Hibernate:
insert
into
GG_EMPLOYEE
(NAME, SALARY, EMAIL, DEPT_ID)
values
(?, ?, ?, ?)
Hibernate:
select
employee0_.ID as ID1_1_,
employee0_.NAME as NAME2_1_,
employee0_.SALARY as SALARY3_1_,
employee0_.EMAIL as EMAIL4_1_,
employee0_.DEPT_ID as DEPT_ID5_1_
from
GG_EMPLOYEE employee0_
where
employee0_.ID=10
1
我在进行了第一次HQL查询后又对了数据表进行了增加操作了,此时的数据表已经发生了改变了,此时查询缓存被关闭了(就算更新操作对我HQL语句查询的结果没影响,但是查询缓存还是被关闭了)