zoukankan      html  css  js  c++  java
  • Hibernate(二)

    性能分析

    抓取策略

    研究对象

    研究怎么样提取集合的,该策略应该作用与set元素上

    研究从一的一方加载多的一方

    案例

    查询cid为1的班级的所有的学生

    明:通过一条sql语句:左外链接,把classes与student表的数据全部提取出来

    查询所有的班级的所有的学生

    该需求翻译过来含有子查询

    如果含有子查询,必须用subselect

    查询班级为1,2,3,4的所有的学生

    抓取策略总结

    1、  研究对象是集合

    2、  经过分析,如果sql语句中含有了子查询,则用subselect效率比较高

    3、  如果页面上需要一次性把两张表的数据全部提取出来,用join效率比较高

    因为采用”join”为左外链接

    4、  如果用select,先查询班级,后查询学生,如果查询班级的个数超过1个,会导致n+1条sql语句

    5、  抓取策略是hibernate提供的一种优化方式而已

    延迟加载

    概念

           需要用到该数据的时候才要加载

    种类

    类的延迟加载

    案例

    说明:

    1、  执行22行代码的时候,不发出sql语句,说明类的延迟加载和主键没有关系

    2、  执行23行代码的时候,发出sql语句,说明只有在得到具体属性的时候才要发出sql语句。

    3、  Session.load方法返回的对象是

    而该对象是由javassist的jar包生成的,从代码结构可以看出该代理对象是持久化类的子类。

    4、  在Classes.hbm.xml文件中

    Lazy的属性默认为true

         5、如果把上述的lazy改成false,则类的延迟加载不起作用了,默认为延迟加载。

    集合的延迟加载

    案例一

    值说明

     默认情况是true,当遍历集合的时候发出sql语句

      Lazy的值为false,当加载classes的时候就把student加载出来了

      Extra是更进一步的延迟加载策略,如果求大小、平均数、和等

    案例二

    案例三

    manytoone的延迟加载

    No-proxy 延迟加载   默认值

    Proxy是加强版的延迟加载

    因为是通过多的一方加载一的一方,所以对效率影响不大,所以一般情况下用默认值即可

    延迟加载总结:

      延迟加载是通过什么时候发出sql语句来优化性能的。

    抓取策略和延迟加载的结合

    Set集合

    1、  当fetch为join时,lazy失效

    2、  当fetch为select时

    如果lazy为true/extra

            当遍历集合的时候,发出加载集合的sql语句

    如果lazy为false

            当获取班级的时候,发出加载集合的sql语句

    3、  当fetch为subselect时和上面的情况一致。

    二级缓存

    概念:是sessionFactory级别的缓存

    存放的是共有数据 共享数据

    生命周期随着hibernate容器启动就开始了,hibernate销毁结束

    hibernate本身对二级缓存没有实现,是借助第三方插件实现的

    公有数据的特征

    1.一般情况下保持不变

    所有的人都能访问

    访问的频率比较高

    安全性不是特别高的数据

    配置

    1.  hibernate.cfg.xml

    2.src 下的ehcache.xml文件

    3.class映射文件

    案例一

    案例二

    说明:session.save方法不进二级缓存

     案例三

    案例四

    说明:

         执行55行代码的时候,把classes表中的所有的对象进入到了二级缓存中

            执行59行代码的时候,重新从数据库中查找记录

         所以createQuery(hql).list方法能把一个对象放入到二级缓存中,但是不利用二级缓存获取对象。

    案例五

    在classpath的根目录下放置一个ehcache.xml文件

    从上述的配置可以看出,classes对象在内存中存放的数量最多为5个,多余的对象将存在磁盘上。

    查找classes表中所有的对象,在内存中放置5个对象,剩余的对象将被存在磁盘上

    案例六

     

     相当于开启了classes类中的set集合的二级缓存

    把集合放入到了二级缓存中。

    读写策略

           Usage

                  Ready-only

                         只能把一个对象放入到二级缓存中不能修改

           Read-write

                能把一个对象放入到二级缓存中,也能修改

    查询缓存

     概念:就是数据缓存 按照需求加载数据

    一级缓存和二级缓存都是对象缓存  表中与多少个字段 就会加载多少个数据

    配置

    1建立在二级缓存基础上

    2开启查询缓存

     案例一

    说明:

           当执行24行代码的时候,发出sql语句

           当执行30行代码的时候,没有发出sql语句,因为利用了查询缓存

    案例二

    说明:

    1、  当两次query.list的时候,都会发出sql语句

    2、  原因是两次的查询hql语句不一样。

    3、  从这里可以看出查询缓存的命中率比较低

    案例三

    从list的内存快照中可以看出,list里存放的不是持久化对象,而是name属性的值。

     一级缓存和二级缓存存放的是持久化对象,如果集合中存放的不是持久化对象,则不能进入二级缓存中,但是能够进入查询缓存中。

    数据缓存和对象缓存

    1、  一级缓存和二级缓存是对象缓存,只能缓存持久化对象

    2、  对象缓存的特别就是要把数据库表中所有的字段全部查询出来

    3、  查询缓存是数据缓存,可以查询一个对象的部分属性,而且可以把部分属性放入到查询缓存中,查询缓存也支持对象。命中率低

    hibernate二级缓存和查询缓存用得比较少

    Hql语句

    单表

    案例一

    from Classes

    案例二

     

    说明:List中含有Object[],该数组中有两个元素,第一个元素为Long类型,第二个元素为String类型。

     案例三

     

    案例四

    案例五

    案例六

    案例七 动态参数

    @Test
        public void testQuery_Dynamic_Parameter(){
            /**
             * key代表持久化类中属性的名称 
             * value代表属性的值
             */
            Map<String, String> map = new HashMap<String, String>();
            map.put("name","aa");
            this.queryDynamic(map, Classes.class);
        }
        
        private void queryDynamic(Map<String, String> map,Class className){
            Session session = sessionFactory.openSession();
            StringBuffer buffer = new StringBuffer();
            /**
             * classes持久化类的元数据
             */
            ClassMetadata classMetadata = sessionFactory.getClassMetadata(className);
            //得到持久化类的名称
            buffer.append("from "+classMetadata.getEntityName());
            buffer.append(" where 1=1");
            //得到map中所有的key值
            Set<String> keys = map.keySet();
            //拼接hql语句:查询条件
            Iterator<String> iterator = keys.iterator();
            for(int i=0;i<keys.size();i++){
                String temp = iterator.next();
                buffer.append(" and "+temp+"=:"+temp);
            }
            Query query = session.createQuery(buffer.toString());
            /**
             * 给所有的查询条件赋值
             */
            for(Entry<String, String> entry:map.entrySet()){
                query.setString(entry.getKey(), entry.getValue());
            }
            List<Classes> classesList = query.list();
            System.out.println(classesList.size());
            session.close();
        }
        
    View Code

    一对多

    案例一

    数据结构不合适,一般不用

    案例二  左外连接

    结构不是很好,数据为object类型数组

    案例三 

    数据为Classes数组

     案例四  迫切内连接

    数据为classes数组

    案例五

    说明:如果用select,则不能用fetch,如果用fetch,则不能用select。

    多对多

    案例一

    案例二

    一对多和多对多 三表内连接

     案例一

     hibernate内部的list

    hibernate内的map

    分页

    public void testDispage(){
            Session session = sessionFactory.openSession();
            Query query = session.createQuery(" from Classes ");
            query.setFirstResult(0);//当前页第一行的在列表中的位置
            query.setMaxResults(2);//当前页有多少行
            List<Classes> classesList = query.list();
            for(Classes c:classesList){
                System.out.println(c.getCid());
            }
            session.close();
        }
    分页

     三种查询方式

    原生的查询方式

    条件查询

    hql语句查询

  • 相关阅读:
    JVM调优--常用JVM监控工具使用
    jvm启动常用参数配置
    公钥和私钥原理
    tcp三次握手四次挥手
    内存泄漏和内存溢出
    hashmap解析
    Visual C++ 6.0 断点调试记录
    C++中输入一组不确定长度的数
    异或
    NULL与nullptr
  • 原文地址:https://www.cnblogs.com/hellowq/p/9647956.html
Copyright © 2011-2022 走看看