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语句查询

 

posted on 2018-09-14 17:34  打酱油的地方  阅读(118)  评论(0编辑  收藏  举报

导航