zoukankan      html  css  js  c++  java
  • 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;
        }
        
        
    }
    View Code

    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;
        }
        
        
    }
    View Code

    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>
    View Code

    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>
    View Code

    第一节:检索策略属性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();
            
        }
    View Code
     
    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();
        }
    View Code
     
    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)
             */
        }
    View Code

    而未设置批量检索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和上面一样。
        
        }
    View Code

    第三节:检索策略属性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 )
             * 
             */
        }
    View Code

    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信息
             */
        }
    View Code
  • 相关阅读:
    18种典型算法
    幂法和反幂法
    关于Ubuntu下安装Win8和Win8下安装Ubuntu的注意事项
    静态链接库与动态链接库
    面向对象系列二(封装)
    基于ASP.NET WPF技术及MVP模式实战太平人寿客户管理项目开发(Repository模式)
    不要对终于用户谈云
    cocos2d-x 3.0 创建项目
    Android OpenGL ES 画球体
    设计模式 适配器模式 以手机充电器为例
  • 原文地址:https://www.cnblogs.com/tenWood/p/7258870.html
Copyright © 2011-2022 走看看