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语句查询的结果没影响,但是查询缓存还是被关闭了)

如果查询缓存没有被关闭,那已是发送一条select语句和一条insert语句,但是现在是发送了两条select语句,一条insert语句 ,所以证明了,当查询缓存相关的表更新后,
查询缓存会自动关闭,这一点需要记住
posted @ 2014-10-13 17:05  Jeremy_software  阅读(479)  评论(0编辑  收藏  举报