重拾Java EEJava 杂谈我爱编程

重拾Java EE——Hibernate(4)杂项

2018-04-10  本文已影响14人  新手村的0级玩家

1 整合log4j(了解)

2 一对一(了解)

2.1 情况1

2.2 情况2

3 二级缓存【掌握】

3.1 介绍

3.1.1 缓存

缓存(Cache): 计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写硬盘(永久性数据存储源)的频率,从而提高应用的运行性能。缓存中的数据是数据存储源中数据的拷贝。缓存的物理介质通常是内存
缓存:程序<--(内存)-->硬盘

3.1.2 什么是二级缓存

3.1.3 二级缓存内部结构


3.1.4 并发访问策略

3.1.5 应用场景

3.1.6 二级缓存提供商

X表示支持

3.2 配置(操作)

1.导入jar包:ehcache-1.5.0.jar/ commons-logging.jar/ backport-util-concurrent.jar
2.开启二级缓存(我要使用二级缓存)
3.确定二级缓存提供商(我要使用哪个二级缓存)
4.确定需要缓存内容
1>配置需要缓存的类
2>配置需要缓存的集合
5.配置ehcache自定义配置文件

3.2.1 导入jar包

3.2.2 开启二级缓存

<!-- 9.1 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>

3.2.3 确定提供商

<!-- 9.2 提供商 -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

3.2.4 确定缓存内容

<!-- 9.3 确定缓存内容 -->
        <!-- 类缓存 -->
        <class-cache usage="read-write" class="com.itheima.a_init.Customer"/>
        <class-cache usage="read-write" class="com.itheima.a_init.Order"/>
        <!-- 集合缓存 -->
        <collection-cache usage="read-write" collection="com.itheima.a_init.Customer.orderSet"/>

3.2.5 ehcache配置文件

步骤1:从jar包复制xml文件

步骤2:将xml重命名“ehcache.xml”


步骤3:将修改后的xml,拷贝到src下

3.3 演示

3.3.1 证明

@Test
public void demo01(){
        //1 证明二级缓存存在 
        // * 修改toString()
        // * 如果二级缓存开启,查询3 没有select语句,表示从二级缓存获得的。
        // * 将二级缓存关闭,查询3将触发select语句。
        Session s1 = factory.openSession();
        s1.beginTransaction();
        
        //1 查询id=1 -- 执行select (查询后,将数据存放在一级缓存,之后由一级缓存同步到二级缓存)
        Customer c1 = (Customer) s1.get(Customer.class, 1);
        System.out.println(c1);
        //2 查询id=1 --从一级缓存获取
        Customer c2 = (Customer) s1.get(Customer.class, 1);
        System.out.println(c2);
        
        s1.getTransaction().commit();
        s1.close();
        
        System.out.println("----------");
        
        Session s2 = factory.openSession();
        s2.beginTransaction();
        
        //3 查询id=1 -- 从二级缓存获取
        Customer c3 = (Customer) s2.get(Customer.class, 1);
        System.out.println(c3);
        
        s2.getTransaction().commit();
        s2.close();
    }

3.3.2 类缓存

@Test
public void demo02(){
       //2 类缓存:只存放数据,散装数据。
       // * 使用默认的toString();
       Session s1 = factory.openSession();
       s1.beginTransaction();
       
       //1 查询id=1 -- 执行select
       Customer c1 = (Customer) s1.get(Customer.class, 1);
       System.out.println(c1);
       //2 查询id=1 -- 从一级缓存获取,一级缓存存放对象本身
       Customer c2 = (Customer) s1.get(Customer.class, 1);
       System.out.println(c2);
       
       s1.getTransaction().commit();
       s1.close();
       
       System.out.println("----------");
       
       Session s2 = factory.openSession();
       s2.beginTransaction();
       
       //3 查询id=1 -- 对象不一样,数据一样
       Customer c3 = (Customer) s2.get(Customer.class, 1);
       System.out.println(c3);
       
       s2.getTransaction().commit();
       s2.close();
   }

3.3.3 集合缓存

@Test
public void demo03(){
       //3 集合缓存:只存放关联对象OID的值,如果需要数据,从类缓存中获取。
       // * 3.1 默认:第一条select 查询客户,第二天 select 查询客户所有订单
       // * 3.2 操作:在hibernate.cfg.xml 将 Order 类缓存删除
       // *** <!--  <class-cache usage="read-write" class="com.itheima.a_init.Order"/>-->
       // *** 多了10条select,通过订单的id查询订单
       Session s1 = factory.openSession();
       s1.beginTransaction();
       
       //1 查询id=1 
       Customer c1 = (Customer) s1.get(Customer.class, 1);
       System.out.println(c1);
       //2 获得订单
       for (Order o1 : c1.getOrderSet()) {
           System.out.println(o1);
       }
       
       
       s1.getTransaction().commit();
       s1.close();
       
       System.out.println("----------");
       
       Session s2 = factory.openSession();
       s2.beginTransaction();
       
       //3 查询id=1
       Customer c3 = (Customer) s2.get(Customer.class, 1);
       System.out.println(c3);
       //4 获得订单
       for (Order o2 : c3.getOrderSet()) {
           System.out.println(o2);
       }
       
       s2.getTransaction().commit();
       s2.close();
   }

3.3.4 时间戳

@Test
public void demo04(){
        //4 时间戳: 所有的操作都会在时间戳中进行记录,如果数据不一致,将触发select语句进行查询
        // * 修改toString()
        Session s1 = factory.openSession();
        s1.beginTransaction();
        
        //1 查询id=1 
        Integer cid = 1;
        Customer c1 = (Customer) s1.get(Customer.class, cid);
        System.out.println(c1);
        //2 绕过一级和二级缓存,修改数据库,修改客户cname=大东哥
        s1.createQuery("update Customer set cname = ? where cid = ?")
            .setString(0, "大东哥")
            .setInteger(1, cid)
            .executeUpdate();
        //3打印
        System.out.println(c1);
        
        s1.getTransaction().commit();
        s1.close();
        
        System.out.println("----------");
        
        Session s2 = factory.openSession();
        s2.beginTransaction();
        
        //4 查询id=1  -- ?
        Customer c3 = (Customer) s2.get(Customer.class, 1);
        System.out.println(c3);
        
        s2.getTransaction().commit();
        s2.close();
    }

3.3.5 查询缓存

步骤一:开启查询缓存

    <!-- 9.4 开启查询缓存 -->
        <property name="hibernate.cache.use_query_cache">true</property>

步骤二:在查询query对象,设置缓存内容(注意:存放和查询 都需要设置)


@Test
public void demo05(){
        //5 查询缓存
        Session s1 = factory.openSession();
        s1.beginTransaction();
        
        //1 query查询
        Query q1 = s1.createQuery("from Customer");
        q1.setCacheable(true);
        List<Customer> a1 = q1.list();
        for (Customer c1 : a1) {
            System.out.println(c1);
        }
        
        //2 cid =1  -- 一级缓存获得
        Customer customer = (Customer) s1.get(Customer.class, 1);
        System.out.println(customer);
        
        s1.getTransaction().commit();
        s1.close();
        
        System.out.println("----------");
        
        Session s2 = factory.openSession();
        s2.beginTransaction();
        
        //2 cid =1  -- 二级缓存获得
        Customer customer2 = (Customer) s2.get(Customer.class, 1);
        System.out.println(customer2);
        
        //3 query查询
        Query q2 = s2.createQuery("from Customer");
        q2.setCacheable(true);
        List<Customer> a2 = q2.list();
        for (Customer c2 : a2) {
            System.out.println(c2);
        }
        
        s2.getTransaction().commit();
        s2.close();
    }

3.4 ehcache配置文件

    <defaultCache> 所有的缓存对象默认的配置
    <cache name="类"> 指定对象单独配置
maxElementsInMemory="10000"  内存最大数
eternal="false"  是否永久(内存常驻留)
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"  内存满了,是否写入到硬盘
maxElementsOnDisk="10000000"  硬盘最大数
diskPersistent="false"  关闭JVM,是否将内存保存硬盘中
diskExpiryThreadIntervalSeconds="120"  轮询
memoryStoreEvictionPolicy="LRU"
    Least Recently Used (specified as LRU). 
    First In First Out (specified as FIFO) 
    Less Frequently Used (specified as LFU)

• maxElementsInMemory :设置基于内存的缓存中可存放的对象最大数目
• eternal:设置对象是否为永久的,true表示永不过期,此时将忽略timeToIdleSeconds 和 timeToLiveSeconds属性; 默认值是false
• timeToIdleSeconds:设置对象空闲最长时间,以秒为单位, 超过这个时间,对象过期。当对象过期时,EHCache会把它从缓存中清除。如果此值为0,表示对象可以无限期地处于空闲状态。
• timeToLiveSeconds:设置对象生存最长时间,超过这个时间,对象过期。
如果此值为0,表示对象可以无限期地存在于缓存中. 该属性值必须大于或等于 timeToIdleSeconds 属性值
• overflowToDisk:设置基于内在的缓存中的对象数目达到上限后,是否把溢出的对象写到基于硬盘的缓存中
• diskPersistent 当jvm结束时是否持久化对象 true false 默认是false
• diskExpiryThreadIntervalSeconds 指定专门用于清除过期对象的监听线程的轮询时间
• memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)

上一篇下一篇

猜你喜欢

热点阅读