Hibernate学习9—检索策略

本章,采用Class和Student     ——  1 对 多的关系;

Student.java:

package com.cy.model;

public class Student {
    private int id;
    private String name;
    private Class c;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Class getC() {
        return c;
    }
    public void setC(Class c) {
        this.c = c;
    }

}

Class.java:

package com.cy.model;

import java.util.HashSet;
import java.util.Set;

public class Class {
    private int id;
    private String name;
    private Set<Student> students = new HashSet<Student>();

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Set<Student> getStudents() {
        return students;
    }
    public void setStudents(Set<Student> students) {
        this.students = students;
    }

}

Student.hbm.xml:

<hibernate-mapping package="com.cy.model">

    <class name="Student" table="t_student">
        <id name="id" column="stuId">
            <generator class="native"></generator>
        </id>
        <property name="name" column="stuName"></property>

        <many-to-one name="c" column="classId" class="com.cy.model.Class" cascade="save-update" lazy="proxy"></many-to-one>

    </class>

</hibernate-mapping>

Class.hbm.xml:

<hibernate-mapping package="com.cy.model">

    <class name="Class" table="t_class">
        <id name="id" column="classId">
            <generator class="native"></generator>
        </id>
        <property name="name" column="className"></property>

        <set name="students" cascade="save-update" inverse="true" lazy="false" batch-size="3" fetch="join">
            <key column="classId"></key>
            <one-to-many class="com.cy.model.Student" />
        </set>
    </class>

</hibernate-mapping>

第一节:检索策略属性Lazy                                                  

Lazy:true:默认延迟检索:用到才加载

    @Test
    public void testLazy1(){
        //因为在class.hbm中set端,一对多,配置的是lazy=true,加载class的时候,默认是不加载学生的。
        Class c = (Class) session.get(Class.class, 1);    

        //等到什么时候会查询学生数据?——等到他用的时候
        //等到用到的时候才去检索,这就是延迟检索
        Set<Student> students = c.getStudents();

        System.out.println(students.size());

//        Iterator it = students.iterator();

    }

lazy:false: 查询class,如果肯定会用到student信息的话,可以立即检索;设置lazy false也行的

lazy:extra:也是延迟的,但是增强的;

比如:配置lazy为true的话,想知道查询出来学生数量的话:

Class c = (Class) session.get(Class.class, 1);

Set<Student> students = c.getStudents();

System.out.println(students.size());

发出的sql为查询所有学生,然后知道3条记录;

但是其实只需要select count(*) from student就行了,这就是sql优化。配置lazy=extra就能实现;

但是实际开发用的也不多,因为很少只查询size的情况;

lazy:proxy:

取Student信息的时候,里面的班级Class是代理类,是不包含数据的;但是用到Class里面内容的时候,就通过代理类去数据库查询内容了。

    @Test
    public void testLazy2(){
        //many to one端,默认lazy - proxy。取出的student中的Class是一个代理类。没有实际数据
        Student student = (Student) session.get(Student.class, 1);

        //等到用到class的名字的时候,代理类才去发出sql查询数据。
        student.getC().getName();
    }

lazy:no-proxy:

没有代理类,取student的时候,里面的class是个null值,等到用class内容了,再去查。很少用.......

第二节:检索策略属性batch-size                                          

1,批量延迟检索;

对应的class.hbm配置:lazy="true" batch-size="3"

/**
     * 批量延迟检索,lazy=true
     */
    @Test
    public void testBatch1(){
        List<Class> classList = session.createQuery("from Class").list();
        Iterator<Class> it = classList.iterator();
        Class c1 = it.next();
        Class c2 = it.next();
        Class c3 = it.next();
        c1.getStudents().iterator();
        c2.getStudents().iterator();
        c3.getStudents().iterator();

        //先取出所有class,因为set students端配置了lazy=false
        //等到c1、c2、c3用到student的时候,才去查找。每个发出一条sql语句。
        //假如classList很多很多的话,遍历每个class,然后取每个class下面的students,每个都发出一条sql,这样效率就很低了。
        //所以,引入了batch-size,批量检索。batch-size的值为批量的值

        //在class.hbm.  set studens端,配置batch-size=3,发出的sql就是这样了:
        /**
         * SELECT
                t_student.classId ,
                t_student.stuId ,
                t_student.stuName
            FROM t_student
            WHERE t_student.classId IN (1, 2, 3)
         */
    }

而未设置批量检索batch-size,发出的sql是下面这样,一条一条的查:

设置了批量检索,batch-size=3后,查询student信息时,一次查3条;

2,批量立即检索;

@Test
    public void testBatch2(){
        List<Class> classList = session.createQuery("from Class").list();
        //这里class.hbm.xml set students中配置lazy=false,batch-size=3,就是批量立即检索了.
        //发出的批量sql和上面一样。

    }

第三节:检索策略属性Fetch                                      

Fetch这里也是在class端配置的;

fetch:subselect,在数据量很大的时候,使用子查询,可以使性能得到优化点。

@Test
    public void testFetch1(){
        List<Class> classList = session.createQuery("from Class").list();
        Iterator<Class> it = classList.iterator();
        Class c1 = it.next();
        Class c2 = it.next();
        Class c3 = it.next();
        c1.getStudents().iterator();
        c2.getStudents().iterator();
        c3.getStudents().iterator();
        /**
         * class.hbm set students 配置fetch="select",是默认的,发出的sql:
         * SELECT
                t_student.classId ,
                t_student.stuId ,
                t_student.stuName
            FROM t_student
            WHERE t_student.classId IN (1, 2, 3)

            现在改为fetch=subselect:sql变成了:
            SELECT
                t_student.classId ,
                t_student.stuId ,
                t_student.stuName
            FROM t_student
            WHERE t_student.classId IN
            (SELECT classId FROM t_class )
         *
         */
    }

fetch:join:

@Test
    public void testFetch2(){
        Class c = (Class) session.get(Class.class, 1);
        /**
         * 这里class.hbm配置:<set name="students" lazy="false" fetch="join">
         * 查询班级的时候,把属于这个班级的学生也一起查出来,这里fetch=join,sql中left outer join:
         * 发出的sql:
         * SELECT
                t_class.classId,
                t_class.className,
                t_student.stuId,
                t_student.stuName,
                t_student.classId
            FROM t_class
            LEFT OUTER JOIN t_student ON t_class.classId = t_student.classId
            WHERE t_class.classId = 1

         * 可以看到只发出一条sql语句了,t_class表和t_student表关联,将class信息和student信息一起取了出来;
         *
         * 而如果fetch为select,是先取班级信息;再取student信息
         */
    }

时间: 2024-11-13 10:42:03

Hibernate学习9—检索策略的相关文章

Hibernate学习之检索策略

一.类级别的检索策略 类级别可选的检索策略包括立即检索和延迟检索, 默认为延迟检索 –立即检索: 立即加载检索方法指定的对象 –延迟检索: 延迟加载检索方法指定的对象,在使用具体的属性时,再进行加载 类级别的检索策略可以通过 <class> 元素的 lazy 属性进行设置,如果程序加载一个对象的目的是为了访问它的属性, 可以采取立即检索:如果程序加载一个持久化对象的目的是仅仅为了获得它的引用, 可以采用延迟检索.注意出现懒加载异常! –无论 <class> 元素的 lazy 属性是

Hibernate复习(六)检索策略

1.立即检索策略 默认的检索策略. 缺点: select语句的数目太多,需要频繁的访问数据库,会影响检索性能.如果需要查询n个Customer对象,那么必须执行n+1次select查询语句. 这种检索策略没有利用SQL的连接查询功能.利用left join 只需一条sql语句既可以实现N+1次查询的结果.并且可能造成内存空间的浪费. 2.延迟策略 在一对多关联级别中对于<set>元素,应该优先考虑使用延迟检索策略. ? 优点 – 由应用程序决定需要加载哪些对象,可以避免执行多余的select语

[原创]java WEB学习笔记88:Hibernate学习之路-- -Hibernate检索策略(立即检索,延迟检索,迫切左外连接检索)

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

Hibernate的检索策略

hibernate 的中的session依照load()和get()按照参数的制定OID(ObjctID)去加载一个持久化对象.另外Query.list()方法则按照HQL语句去加载持久化的对象. 以上的几个方式都可以实现hibernate的持久化对象的加载.如果有不懂hibernate对象的"临时状态"."游离态"."持久态"."删除状态"的小伙伴,自己先去了解下. 对于hibernate的以上的几种检索策略,我们先来了解下

hibernate(八) Hibernate检索策略(类级别,关联级别,批量检索)详解

序言 很多看起来很难的东西其实并不难,关键是看自己是否花费了时间和精力去看,如果一个东西你能看得懂,同样的,别人也能看得懂,体现不出和别人的差距,所以当你觉得自己看了很多书或者学了很多东西的时候,你要想想,你花费的也就那么一点时间,别人花你这么多时间也能够学到你所学到的东西,所以还是要继续努力.既然不是天才,唯有靠勤奋来弥补. --WH 一.概述 检索策略分三大块,类级别检索策略和关联级别检测策略. 类级别检索策略:get.load. 关联级别检索策略:order.getCustomer().g

Hibernate 检索策略

概述 检索数据时的 2 个问题: –不浪费内存:当 Hibernate 从数据库中加载 Customer 对象时, 如果同时加载所有关联的 Order 对象, 而程序实际上仅仅需要访问 Customer 对象, 那么这些关联的 Order 对象就白白浪费了许多内存. –更高的查询效率:发送尽可能少的 SQL 语句 类级别的检索策略 •类级别可选的检索策略包括立即检索和延迟检索, 默认为延迟检索 –立即检索: 立即加载检索方法指定的对象 –延迟检索: 延迟加载检索方法指定的对象.在使用具体的属性时

Hibernate检索策略之延迟加载和立即加载

延迟加载:延迟加载(lazy load懒加载)是当在真正需要数据时,才执行SQL语句进行查询.避免了无谓的性能开销. 延迟加载分类:  1.类级别的查询策略 2.一对多和多对多关联的查询策略 3.多对一关联的查询策略 什么情况下使用延迟加载? 如果程序加载一个对象的目的是为了访问它的属性,可以采用立即加载.如果程序加载一个持久化对象的目的是仅仅为了获得它的引用,可以采用延迟加载. 如何配置延时加载? 在Hibernate中通过对.hbm的lazy属性来赋值,不同位置出现lazy的作用和取值也是不

Hibernate检索策略

Hibernate的检索策略主要分为两类: 1. 立即查询:根据id查询,调用get方法,调用get方法马上发送语句查询数据库 2. 延迟查询:根据id查询,还有load方法,调用load方法不会马上发送语句查询数据,只有得到对象里面的值的时候才会发送语句查询数据库. Hibernate的延迟查询又分为两类: 1. 类级别延迟:根据id查询返回实体类对象,调用load方法不会马上发送语句 2. 关联级别延迟:查询某个客户,在查询这个客户的所有联系人,查询客户的所有联系人的过程是否需要延迟,这个过

Hibernate检索策略与检索方式

hibernate的Session在加载Java对象时,一般都会把鱼这个对象相关联的其他Java对象也都加载到缓存中,以方便程序的调用.但很多情况下,我们不需要加载太多无用的对象到缓存中,一来会占用大量的内存,二来会增加数据库的访问次数,使得程序的运行效率降低.为了合理的使用缓存,Hibernate提供了不同的检索策略来解决这些问题. 作用域 在说检索策略之前,先了解一下检索策略的作用域,它分为:类级别和关联级别.类级别的作用域在检索数据时,检索的数据只包含一个类对象,不涉及与该类关联的其他对象