Hibernate笔记(二)

性能优化

延迟加载( lazy):当需要的时候加载,控制sql语句的发出时间来提高性能
1、session.load方法产生的是代理对象
2、session.load方法产生的对象只不过是一个空壳子
当真正加载属性的时候才要发出sql语句
   1、类的延迟加载
       只针对一般属性,不针对(标示符、集合、引用)
   2、集合的延迟加载
       在one-to-many,many-to-many的情况下的类与集合的关联中的集合
       1、是set元素的延迟加载
       2、 true
               当迭代集合的时候,加载集合中的数据(默认值)
          false
               当加载对象的时候,直接把关联的集合对象加载出来了
          extra
               当加载集合的大小的时候,没有必要把集合中的数据加载出来,这个时候用该加载策略比较合适
   3、单端关联(many-to-one)的延迟加载:对性能的影响有限
          many-to-one的 lazy 延迟加载: false/no-proxy(true)/proxy(true) 
     只不过是hibernate提供的一种提高性能的方式,需要映射文件中进行配置,只能配置一次  

抓取策略( fetch):
    针对set集合
       set元素中有一个属性 fetch:
            " select"
               1、默认的
               2、会导致n+1条查询
            " subselect"
                 当经过需求分析翻译成sql语句,含有子查询,这个时候,用这个策略效率最高
            " join"
               1、左外链接
               2、一次性把classes与student全部加载出来
               3、如果需求分析中含有子查询,该策略将失效
     fetch= select + batch-size="2" 相当于subselect


延迟加载( lazy)和抓取策略( fetch):针对set集合
   1、延迟加载:通过什么时候发出sql语句加载集合
   2、抓取策略:通过什么样的sql语句加载集合
    lazy               fetch                     说明
    true               select          当迭代集合的时候发出sql语句,通过每一个cid查询student
    true/false       join             如果需要分析中没有子查询,
                        subselect        一条语句加载classes和student,这个时候lazy可以忽略 

一级缓存:session的缓存
          存放的是私有数据
          因为数据放在了threadlocal中,所以是安全的
   操作一级缓存
       1、一级缓存的生命周期
           等同于session的生命周期
       2、通过什么样的方法把对象放入到一级缓存中
          session.get,save,update方法都可以把对象放入到一级缓存中
       3、通过什么样的方法客户端从一级缓存中把对象提取出来
            session.get方法
       4、什么样把一个对象从一级缓存中清除
           session.evict
       5、怎么样把所有的对象从一级缓存中清除
           session.clear
       6、怎么样把缓存中的对象同步到数据库中
           session.flush
       7、怎么样把数据库中的数据同步到缓存中
           session.reflesh
  一级缓存的意义:
     在操作的过程中,减少和数据库的交互次数,从而提高效率
     快照和副本也是为了减少数据库的交互次数,提高效率的

二级缓存:
   1、数据不能经常更新
   2、公共的,不经常改变的
   3、私有数据,绝密的数据不能存放
   4、是sessionFactory缓存
   5、hibernate没有针对二级缓存的解决方案,是借助第三方类库实现的(jar包)
         ehcache      
         oscache
         jbosscache   分布式缓存
         memorycache  不支持的   分布式缓存
   6、实现步骤
        1、在配置文件中
            1、开启二级缓存
    <property name="cache.use_second_level_cache">true</property>
            2、提供二级缓存的供应商
    <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
使用的二级缓存实现是ehcache,需要配置ehcache.xml
<Cache
   name="com.itheima05.hibernate.domain.Classes"
   maxElementsInMemory="5" 
   eternal="false"<!-- true表示缓存是不是永远不超时 -->
   timeToIdleSeconds="120"<!-- 如果没设置下面的项目,此项才有用 -->
   timeToLiveSeconds="120"<!-- 缓存中每个元素的超时时间 -->
   overflowToDisk="true"<!-- 当往缓存里面put的元素超过maxElementsInMemory的值时,把部分数据保存到硬盘上 -->
   maxElementsOnDisk="10000000"<!-- 设定磁盘缓存大小磁盘缓存大小 -->
   diskPersistent="false"<!-- 如果配置为false,缓存管理器停止后会清楚磁盘缓存。true则保存 -->
   diskExpiryThreadIntervalSeconds="120"<!-- 设置失效监测以及清除工作间隔时间 -->
   memoryStoreEvictionPolicy="LRU"<!-- 默认就好 -->
   />

        2、可以针对类、集合开启二级缓存
           1、类
               1、在配置文件中(没试验过)
                  <class-cache usage="read-only" class="com.itheima05.hibernate.domain.Classes"/>
               2、在映射文件中加入以下标签
                         <cache usage="read-only"/>
           2、集合
               1、先开启集合针对类的二级缓存
               2、再开启集合的二级缓存
        3、使用
              session.get方法把一个对象放入到二级缓存中
              当事务提交的时候,把对象放入到二级缓存中
   7、二级缓存的缓存策略
          <cache usage="read-only"/>
            read-only: 把对象放入到二级缓存中不能进行修改
            read-write:可以把对象放入到二级缓存,也可以修改
   8、利用CacheModel的值限制一级缓存和二级缓存的交互
   9、可以把对象缓存在磁盘上
   10、统计
先设置开启统计机制
<property name="hibernate.generate_statistics">true</property>
session.getStatistics().getEntityCount()
sessionFactory.getStatistics().getSecondLevelCachePutCount()


一级缓存和二级缓存称为对象缓存
   对象缓存(对象在数据库中有对应的表)
      1、对象缓存是根据主键进行标示的
      2、对象缓存会把数据库表中相应的行的所有的字段全部加载到对象中
           如果一个表有50个字段,而需要的是5个字段,这样利用对象缓存
           会把很多没有用的数据加载到缓存中

Query:
   1、query.list和query.iterator的区别
       query.list
           Query query = session.createQuery("from Classes");
           query.setCacheable(true);
           query.list();
                 1、加载的是对象的所有的内容
                 2、该hql语句查询出来的是List<Classes>,正好符合对象缓存,所以
                     该结果会在一级缓存,二级缓存中存储
                 3、如果hql语句是"select name from Classes",查询出来的结果
                      不符合对象缓存,这个时候,结果不会储存在一级缓存和二级缓存中
                 4、当第二次执行query.list的时候,必须设置query.setCacheable(true);
                      才能从查询缓存中提取数据
       query.iterator
           Query query = session.createQuery("from Classes");
           Iterator<Classes> iterator = query.iterate();
           while(iterator.hasNext()){
                Classes classes = iterator.next();
                System.out.println(classes.getName());
           }
                 1、先加载所有的id
                 2、再根据id加载所有的值
                 3、该方法把对象放入到了二级缓存中,查询的时候利用的是二级缓存,不利用查询缓存
       总结:
           1、query.list方法一次那个把数据全部查询出来,而query.iterator方法先查询id,再查询数据
           2、query.list方法利用查询缓存获取数据,但是必须设置query.setCacheable(true)
              query.iterator方法利用二级缓存查询数据
   2、分页
   3、hql
        1、单表
        2、一对多
        3、多对多
        4、一对多和多对多



查询缓存是数据缓存
   数据缓存
      1、数据缓存是根据hql语句进行标示的
  如果想把一些数据放入到查询缓存中,或者从查询缓存中把一些数据提取出来,
  必须通过query对象,而且必须设置query.setCacheable(true)才能做到
  如果想利用查询缓存,则hql必须相同 

      2、能按照需求缓存数据

      3、实现
          1、基于二级缓存
          2、在配置文件中开启查询缓存
              <property name="cache.use_query_cache">true</property>
          3、利用session.createQuery方法,把数据放入到查询缓存中



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值