zoukankan      html  css  js  c++  java
  • 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语句 ,所以证明了,当查询缓存相关的表更新后,
    查询缓存会自动关闭,这一点需要记住
  • 相关阅读:
    超详细的FreeRTOS移植全教程——基于srm32
    继续学习freertos消息队列
    FreeRTOS优化与错误排查方法
    从单片机到操作系统⑦——深入了解FreeRTOS的延时机制
    Android Pie 私人 DNS 使用教程
    「运维之美」技术周刊 ( 第 1 期 )
    「运维之美」技术周刊 ( 第 3 期 )
    用 Python 快速实现 HTTP 和 FTP 服务器
    关于ubuntu软件图标的问题
    You're currently running Fcitx with GUI 错误解决 Fcitx
  • 原文地址:https://www.cnblogs.com/jeremy-blog/p/4022609.html
Copyright © 2011-2022 走看看