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语句 ,所以证明了,当查询缓存相关的表更新后,
    查询缓存会自动关闭,这一点需要记住
  • 相关阅读:
    fedora上部署ASP.NET——(卡带式电脑跑.NET WEB服务器)
    SQL Server 请求失败或服务未及时响应。有关详细信息,请参见事件日志或其它适合的错误日志
    8086CPU的出栈(pop)和入栈(push) 都是以字为单位进行的
    FTP 服务搭建后不能访问问题解决
    指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配
    Linux 安装MongoDB 并设置防火墙,使用远程客户端访问
    svn Please execute the 'Cleanup' command. 问题解决
    .net 操作MongoDB 基础
    oracle 使用绑定变量极大的提升性能
    尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。
  • 原文地址:https://www.cnblogs.com/jeremy-blog/p/4022609.html
Copyright © 2011-2022 走看看