Java笔记之hibernate(十):关系延迟加载

0.说在前面

  基于Hibernate(九):属性延迟加载项目

1.概念

  关系延迟加载是用在one-to-many、many-to-many、many-to-one关系配置上的

  hibernate3之后默认开启关系延迟加载,当前项目就是使用的hibernate3

2.新建LazyTest类

package com.hibernate.demo.test;

import java.util.Set;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;

import com.hibernate.demo.bean.Department;
import com.hibernate.demo.bean.Employee;

public class LazyTest {

    public static void main(String[] args) {
        //加载配置文件,创建会话工厂对象
        SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
        //创建会话对象
        Session session = sessionFactory.openSession();
        
        System.out.println("log1");
        //根据id获取Department对象
        Department department = (Department) session.get(Department.class, 1);
        System.out.println("log2");
        //获取对象中的Employee集合
        Set<Employee> employees = department.getEmployees();
        //遍历集合
        for (Employee employee : employees) {
            System.out.println(employee.getEmpName());
        }
        System.out.println("log3");
        //关闭会话对象
        session.close();
        //关闭会话工厂对象
        sessionFactory.close();
    }

}

说明:Department类Employee类是一对多的关系,此时Department.hbm.xml文件中两者的one-to-many配置上并没有添加延迟加载的配置

3.运行LazyTest类

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
log1
Hibernate: select department0_.dept_id as dept1_2_0_, department0_.dept_name as dept2_2_0_ from t_department department0_ where department0_.dept_id=?
log2
Hibernate: select employees0_.dept_id as dept3_2_1_, employees0_.emp_id as emp1_1_, employees0_.emp_id as emp1_0_0_, employees0_.emp_name as emp2_0_0_, employees0_.dept_id as dept3_0_0_ from t_employee employees0_ where employees0_.dept_id=?
李四
王五
log3

4.总结

  从3中打印的信息,可以看出查询Department时并没有发送SQL去查询Employee信息,而是在获取Employee的Set集合信息时才发送SQL去数据库查询,可见默认是开启延时加载的.

5.修改Department.hbm.xml文件,关闭Department与Employee之间的one-to-many延时加载

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hibernate.demo.bean">
    <!-- 映射Department类与表t_department -->
    <class name="Department" table="t_department">
        <id name="deptId" column="dept_id">
            <!-- 声明主键生成策略为自增 -->
            <generator class="native"></generator>
        </id>
        <property name="deptName" column="dept_name"></property>
        <!-- 用于设置一对多的关系 -->
        <set name="employees" lazy="false">
            <!-- 声明多的一方对应的表中的外键列名,not-null设置可以为空 -->
            <key column="dept_id" not-null="false"></key>
            <!-- 声明一对多的关系,class设置多的一方对应的类名 -->
            <one-to-many class="Employee"/>
        </set>
    </class>
</hibernate-mapping>

6.再次运行LazyTest类

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
log1
Hibernate: select department0_.dept_id as dept1_2_0_, department0_.dept_name as dept2_2_0_ from t_department department0_ where department0_.dept_id=?
Hibernate: select employees0_.dept_id as dept3_2_1_, employees0_.emp_id as emp1_1_, employees0_.emp_id as emp1_0_0_, employees0_.emp_name as emp2_0_0_, employees0_.dept_id as dept3_0_0_ from t_employee employees0_ where employees0_.dept_id=?
log2
李四
王五
log3

7.总结

  从6中打印的信息可以看出,延迟加载被关闭后,在查询Department信息的时候也会发送SQL语句去查询Employee信息

8.关于many-to-one的延迟加载问题,新建LazyTest2类

package com.hibernate.demo.test;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;

import com.hibernate.demo.bean.Department;
import com.hibernate.demo.bean.Employee;

public class LazyTest2 {

    public static void main(String[] args) {
        //加载配置文件,创建会话工厂对象
        SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
        //创建会话对象
        Session session=sessionFactory.openSession();
        
        System.out.println("log1");
        //根据id获取Employee对象
        Employee employee = (Employee) session.get(Employee.class, 2);
        System.out.println("log2");
        //获取Department对象
        Department department = employee.getDepartment();
        System.out.println(department.getDeptName());
        System.out.println("log3");
        
        //关闭会话对象
        session.close();
        //关闭会话工厂对象
        sessionFactory.close();
        
    }

}

9.运行LazyTest2类

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
log1
Hibernate: select employee0_.emp_id as emp1_0_0_, employee0_.emp_name as emp2_0_0_, employee0_.dept_id as dept3_0_0_ from t_employee employee0_ where employee0_.emp_id=?
log2
Hibernate: select department0_.dept_id as dept1_2_0_, department0_.dept_name as dept2_2_0_ from t_department department0_ where department0_.dept_id=?
Hibernate: select employees0_.dept_id as dept3_2_1_, employees0_.emp_id as emp1_1_, employees0_.emp_id as emp1_0_0_, employees0_.emp_name as emp2_0_0_, employees0_.dept_id as dept3_0_0_ from t_employee employees0_ where employees0_.dept_id=?
行政部
log3

说明:Employee.hbm.xml文件中关于Employee与Department的多对一配置中并没有手动设置延迟加载,而是使用的默认的延迟加载配置.

10.总结

  从9中打印的信息可以看出,many-to-one是默认开启延迟加载的,不需要手动开启,如果手动开启反倒会报异常:Attribute "lazy" with value "true" must have a value from the list "false proxy no-proxy ".

11.将Employee.hbm.xml文件中与Department的many-to-one配置的延迟加载关闭,也就是设置lazy="false",再次运行LazyTest2类

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
log1
Hibernate: select employee0_.emp_id as emp1_0_0_, employee0_.emp_name as emp2_0_0_, employee0_.dept_id as dept3_0_0_ from t_employee employee0_ where employee0_.emp_id=?
Hibernate: select department0_.dept_id as dept1_2_0_, department0_.dept_name as dept2_2_0_ from t_department department0_ where department0_.dept_id=?
Hibernate: select employees0_.dept_id as dept3_2_1_, employees0_.emp_id as emp1_1_, employees0_.emp_id as emp1_0_0_, employees0_.emp_name as emp2_0_0_, employees0_.dept_id as dept3_0_0_ from t_employee employees0_ where employees0_.dept_id=?
log2
行政部
log3

12.总结

  从11中打印的信息可以看出,关闭了延迟加载,在查询Employee信息的时候也会发送SQL语句查询Department信息

13.综述

  从上述各种情况的结果来看:

    (1).hibernate3之后是默认开启延迟加载的;

    (2).one-to-many、many-to-many、many-to-one虽然都是默认开启延迟加载的,但是前两者还可以手动开启延迟加载,最后一个就不可以手动开启延迟加载;

    (3).many-to-many没有做示例,但也确实是默认开启延迟加载的;

posted @ 2020-04-24 15:16  安徒生敲代码  阅读(163)  评论(0编辑  收藏  举报