4.0、Hibernate-延迟加载 2

4.0、Hibernate-延迟加载 2

        消费者 和 订单 属于 一对多 的 关系,通过上一章节 3.0 的内容我们知道了可以通过设置 customer 来实现延迟加载,本章节来介绍一下如何设置 orders 去实现延迟加载;

        one-to-many 的 lazy 默认是 true 是开启的,先比较之下 many-to-one 默认是 false 是关闭的;

第一步:将order.hbm.xml 文件中改为 lazy = false,customer.hbm.xml 不变仍旧是 lazy = extra ->

<many-to-one name="customer" class="com.hkl.pojo.Customer" column="cid" lazy="false"></many-to-one>

第二步:创建 Test5.java 测试文件,如下所示 ->

import com.hkl.pojo.Order;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test5 {
    public static void main(String[] args) {
        //        创建configuration
        Configuration configuration = new Configuration().configure();
//        获取sessionFactory
        SessionFactory sessionFactory = configuration.buildSessionFactory();
//        获取Session
        Session session = sessionFactory.openSession();

        Order order = session.get(Order.class,3);
        System.out.println(order);
        session.close();
    }
}

第三步:运行 Test5.java 文件,运行结果 如下所示 -> 

可以看到执行了两条 SQL 语句;

第四步:将 Order.hbm.xml 中的 lazy 设置为 proxy ->

<many-to-one name="customer" class="com.hkl.pojo.Customer" column="cid" lazy="proxy"></many-to-one>

第五步:再次运行 Test5.java,结果如下图所示->

 可以看到只有一条SQL语句了;

第六步:将Test5.java 文件中的 System.out.println(order); 改为以下语句时,再去运行 ->

System.out.println(order.getCustomer());

可以发现又变回两条SQL语句了->

那么这里再补充一下关于 proxy 和 no-proxy 的区别:

        no-proxy:当调用方法需要访问customer的成员变量时,发送 SQL 语句查询 Customer,否则不查询;

        proxy:无论调用方式是否需要访问 customer 的成员变量,都会发送 SQL 语句查询 Customer;

下面来说一下 多对多 的关系如何对操作 ->

多对多关系 课程与学生 -> 查询 课程 Course ,加载对应的 学生 Account ,默认延迟加载开启;

第一步:首先创建两个pojo实体类文件,Account.java 和 Course.java 和他们相对应的 xml 映射文件 ,如下所示->

Account.java->

package com.hkl.pojo;
import java.util.Set;

public class Account {
    private Integer id;
    private String name;
    private Set<Course> courses;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Course> getCourses() {
        return courses;
    }

    public void setCourses(Set<Course> courses) {
        this.courses = courses;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

Course.java -> 

package com.hkl.pojo;
import java.util.Set;

public class Course {
    private Integer id;
    private String name;
    private Set<Account> accounts;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Account> getAccounts() {
        return accounts;
    }

    public void setAccounts(Set<Account> accounts) {
        this.accounts = accounts;
    }

    @Override
    public String toString() {
        return "Course{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

Course.hbm.xml 映射文件如下所示->

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

    <class name="com.hkl.pojo.Course" table="t_course">
        <!--        主键映射,数据库表中的主键字段用 id 配置,而 name = "id" 这个 id 指的是 Account 实体类中的 id 属性名-->
        <id name="id" type="java.lang.Integer">
            <!--            数据库表 id 主键字段配置-->
            <column name="id"></column>
            <!--            设置主键自增方式 -> identity-->
            <generator class="identity"></generator>
        </id>
        <property name="name" type="java.lang.String">
            <column name="name"></column>
        </property>

        <!--courses是实体类Course中的属性名,该属性是一个 Course 类的集合,所以对应表 account_course-->
        <set name="accounts" table="account_course" lazy="true">
            <!--这里配置一下主外键 aid -->
            <key column="cid"></key>
            <!--学生和选课的关系是多对多,所以这里是 many-to-many,然后给set类型加一个对象,对象类型是Course , column是course在这个中间表中的外键cid-->
            <many-to-many class="com.hkl.pojo.Account" column="aid"></many-to-many>
        </set>
    </class>

</hibernate-mapping>

Account.hbm.xml 映射文件如下所示->

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

    <class name="com.hkl.pojo.Account" table="t_account">
        <!--        主键映射,数据库表中的主键字段用 id 配置,而 name = "id" 这个 id 指的是 Course 实体类中的 id 属性名-->
        <id name="id" type="java.lang.Integer">
            <!--            数据库表 id 主键字段配置-->
            <column name="id"></column>
            <!--            设置主键自增方式 -> identity-->
            <generator class="identity"></generator>
        </id>
        <property name="name" type="java.lang.String">
            <column name="name"></column>
        </property>

        <!--courses是实体类Course中的属性名,该属性是一个 Course 类的集合,所以对应表 account_course-->
        <set name="courses" table="account_course">
            <!--这里配置一下主外键 cid -->
            <key column="aid"></key>
            <!--学生和选课的关系是多对多,所以这里是 many-to-many,然后给set类型加一个对象,对象类型是Account , column是account在这个中间表中的外键aid-->
            <many-to-many class="com.hkl.pojo.Course" column="cid"></many-to-many>
        </set>
    </class>

</hibernate-mapping>

第二步:创建测试 Test6.java 文件如下所示->

import com.hkl.pojo.Course;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test6 {

    public static void main(String[] args) {
        //        创建configuration
        Configuration configuration = new Configuration().configure();
//        获取sessionFactory
        SessionFactory sessionFactory = configuration.buildSessionFactory();
//        获取Session
        Session session = sessionFactory.openSession();

        Course course = session.get(Course.class,1);
        System.out.println(course);
        session.close();
    }

}

运行结果如下所示 ->

 可以发现只有一条 SQL 语句;

 第三步:将 Test6.java 测试文件中的 System.out.println(course);  改为 ->

System.out.println(course.getAccounts());

再去运行,结果如下图所示 ->

 可以看到执行了三条 SQL 语句【因为 多对多 关系之间有三张表】;

这里我们先把 Course.hbm.xml 中的 lazy 设置为 false 关掉延迟加载 ->

        <set name="accounts" table="account_course" lazy="false">
            <!--这里配置一下主外键 aid -->
            <key column="cid"></key>
            <!--学生和选课的关系是多对多,所以这里是 many-to-many,然后给set类型加一个对象,对象类型是Course , column是course在这个中间表中的外键cid-->
            <many-to-many class="com.hkl.pojo.Account" column="aid"></many-to-many>
        </set>

        然后去运行 Test6.java 不管我们有没有级联操作都是执行两条 SQL 语句,而之前开启 延迟加载 之后会发现,当不涉及级联操作的时候就是一条 SQL 语句,涉及级联操作的时候才会变成两条 SQL 语句;

        那么 多对多 关系两边是都一样的,这里 Account 和 Course 相同,所以 Account 就不做演示了;

        这里和 一对多 的区别就是,当涉及级联操作的时候,一对多只需要查询两张表即可,而多对多关系中,需要三张表才能将他们两个关联起来,所以当多对多涉及级联操作的时候会执行三条 SQL 语句;如下图所示->

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值