Mybatis的延迟加载和立即加载


示例:在一对多中,当我们有一个用户,他有100个帐户

问题1:在查询用户时,要不要把关联的账户查出来?

问题2:在查询账户时,要不要把关联的用户信息查出来?

问题1:在查询用户时,要不要把关联的账户查出来?

用户和帐户之间的关系应该是一对多的关系,一个用户对应多个账户,如果在查询用户时,同时查询到他关联的帐户,那么这些查询到的账户信息就会占据很大的内存,所以应该是是么时候使用,是么时候才查询帐户信息。

问题2:在查询账户时,要不要把关联的用户信息查出来?

帐户和用户之间的关系应该是一对一的,一个帐户应该对应一个用户,如果查询账户时,账户的所属用户信息应该是随着一起查询出来的,且用户信息占据内存很小。

延迟加载:(应用于一对多,多对多,即关联的对象为“多”时)

在真正使用数据时才发起查询,不用的时候不查询,按需加载(懒加载)。

立即加载:(应用于多对一,一对一,即关联的对象为“一”时)

不管用不用,在调用方法的时候就立即执行,马上发起查询。


一对一实现延迟:account-user 的一对一延迟加载

帐户account实体类
 package com.itheima.domain;
 ​
 import java.io.Serializable;
 ​
 /**
  * @Author: lijiahao
  * @Description:
  * @Data: Create in 12:23 2020/2/26
  * @Modified By:
  */
 public class Account implements Serializable {
     private Integer id;
     private Integer uid;
     private Double money;
 ​
     //从表实体应该包含一个主表实体的对象引用
     private User user;
 ​
     public User getUser() {
         return user;
    }
 ​
     public void setUser(User user) {
         this.user = user;
    }
 ​
     public Integer getId() {
         return id;
    }
 ​
     public void setId(Integer id) {
         this.id = id;
    }
 ​
     public Integer getUid() {
         return uid;
    }
 ​
     public void setUid(Integer uid) {
         this.uid = uid;
    }
 ​
     public Double getMoney() {
         return money;
    }
 ​
     public void setMoney(Double money) {
         this.money = money;
    }
 ​
     @Override
     public String toString() {
         return "account{" +
                 "id=" + id +
                 ", uid=" + uid +
                 ", money=" + money +
                 '}';
    }
 }
user的接口
 package com.itheima.dao;
 ​
 import com.itheima.domain.User;
 ​
 import java.util.List;
 ​
 /**
  * @Author: lijiahao
  * @Description: 用户的持久层接口
  * @Data: Create in 21:42 2020/2/22
  * @Modified By:
  */
 public interface IUserDao {
 ​
     //查询所有用户,同时获取到用户下所有账户的信息
     List<User> findAll();
 ​
     //根据id查询用户信息
     User findById(Integer userId);
 ​
 }
主配置文件
 <?xml version="1.0" encoding="utf-8" ?>
 <!DOCTYPE configuration
         PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-config.dtd">
 ​
 <!--mybatis的主配置文件-->
 <configuration>
     <!--配置连接池-->
     <properties resource="jdbcConfig.properties"/>
 ​
     <!--配置参数-->
     <settings>
         <!--开启mybatis延迟加载,默认为false-->
         <setting name="lazyLoadingEnabled" value="true"/>
         <!--开启立即加载,mybatis3.4.1以上默认为false-->
         <setting name="aggressiveLazyLoading" value="false"/>
     </settings>
     <!--配置别名 类名就是别名,不区分大小写-->
     <typeAliases>
         <package name="com.itheima.domain" ></package>
     </typeAliases>
 ​
     <!--配置环境-->
     <environments default="mysql">
         <!--配置mysql的环境-->
         <environment id="mysql">
             <!--配置事务的类型-->
             <transactionManager type="JDBC"></transactionManager>
             <!--配置数据源(连接池)-->
             <dataSource type="POOLED">
                 <!--配置数据库的四个基本信息-->
                 <property name="driver" value="${jdbc.driver}" />
                 <property name="url" value="${jdbc.url}"/>
                 <property name="username" value="${jdbc.username}" />
                 <property name="password" value="${jdbc.password}" />
             </dataSource>
         </environment>
     </environments>
 ​
     <!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
     <mappers>
         <package name="com.itheima.dao"></package>
     </mappers>
 </configuration>
帐户映射配置文件IAccountDao.xml
 <?xml version="1.0" encoding="utf-8" ?>
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 ​
 <mapper namespace="com.itheima.dao.IAccountDao">
 ​
 ​
     <!--定义封装account和user的ResultMap account为主表,user为从表,实现一对一-->
     <resultMap id="accountUserMap" type="account">
         <!--主键配置,property为属性名,column为数据库列名(sql语句起了别名as后面的,下方sql语句可以搜索到的)-->
         <!--aid为-->
         <id property="id" column="id"></id>
         <result property="uid" column="uid"></result>
         <result property="money" column="money"></result>
         <!--一对一的关系映射,配置封装user的内容
         select属性指定的内容:查询用户的唯一标识
         column属性指定的内容:用户根据id查询时,所需要的参数的值-->
         <association property="user" column="uid" javaType="user" select="com.itheima.dao.IUserDao.findById">
 ​
         </association>
     </resultMap>
     <!--查询所有-->
     <select id="findAll" resultMap="accountUserMap">
         select * from account
     </select>
 ​
 </mapper>
测试类
 package com.itheima;
 ​
 import com.itheima.dao.IAccountDao;
 import com.itheima.domain.Account;
 import org.apache.ibatis.io.Resources;
 import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSessionFactory;
 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 ​
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
 ​
 /**
  * @Author: lijiahao
  * @Description:
  * @Data: Create in 22:56 2020/2/22
  * @Modified By:
  */
 public class AccountTest {
 ​
     private InputStream in;
     private SqlSession sqlSession;
     private IAccountDao accountDao;
 ​
     @Before
     public void init() throws IOException {
         //1.读取配置文件
         in = Resources.getResourceAsStream("SqlMapConfig.xml");
         //2.创建SqlSessionFactory工厂
         SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
         SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
         sqlSession = sqlSessionFactory.openSession(true);
         //3.使用工厂生产dao对象
         accountDao = sqlSession.getMapper(IAccountDao.class);
    }
 ​
     @After
     public void destory() throws IOException {
         in.close();
    }
 ​
     @Test
     public void testFindAll() throws IOException {
         //5.使用代理对象执行方法
         List<Account> accounts = accountDao.findAll();
         for (Account account : accounts) {
             System.out.println(account);
             System.out.println(account.getUser());
        }
    }
 ​
 ​
 }

一对多实现延迟加载:user-account 的一对多的延迟加载

用户user实体类
 package com.itheima.domain;
 ​
 import java.io.Serializable;
 import java.util.Date;
 import java.util.List;
 ​
 /**
  * @Author: lijiahao
  * @Description:
  * @Data: Create in 21:37 2020/2/22
  * @Modified By:
  */
 public class User implements Serializable {
     private Integer id;
     private String username;
     private Date birthday;
     private String sex;
     private String address;
 ​
     //一对多关系映射,主表实体应该包含从表实体的集合引用
     private List<Account> accounts;
 ​
     public List<Account> getAccounts() {
         return accounts;
    }
 ​
     public void setAccounts(List<Account> accounts) {
         this.accounts = accounts;
    }
 ​
     public Integer getId() {
         return id;
    }
 ​
     public void setId(Integer id) {
         this.id = id;
    }
 ​
     public String getUsername() {
         return username;
    }
 ​
     public void setUsername(String username) {
         this.username = username;
    }
 ​
     public Date getBirthday() {
         return birthday;
    }
 ​
     public void setBirthday(Date birthday) {
         this.birthday = birthday;
    }
 ​
     public String getSex() {
         return sex;
    }
 ​
     public void setSex(String sex) {
         this.sex = sex;
    }
 ​
     public String getAddress() {
         return address;
    }
 ​
     public void setAddress(String address) {
         this.address = address;
    }
 ​
     @Override
     public String toString() {
         return "User{" +
                 "id=" + id +
                 ", username='" + username + '\'' +
                 ", birthday=" + birthday +
                 ", sex='" + sex + '\'' +
                 ", address='" + address + '\'' +
                 '}';
    }
 }
 ​
account的接口
 package com.itheima.dao;
 ​
 import com.itheima.domain.Account;
 ​
 import java.util.List;
 ​
 /**
  * @Author: lijiahao
  * @Description:
  * @Data: Create in 12:25 2020/2/26
  * @Modified By:
  */
 public interface IAccountDao {
     /**
      * @Author Lijiahao
      * @Description 查询所有账户, 同时还要获取到当前账户的所有信息
      * @Date 16:32 2020/2/26
      * @Param []
      * @return java.util.List<com.itheima.domain.Account>
      **/
     List<Account> findAll();
 ​
     //根据用户id查询帐户信息
     List<Account> findAccountByUid(Integer uid);
 ​
 }
主配置文件
 package com.itheima.domain;
 ​
 import java.io.Serializable;
 import java.util.Date;
 import java.util.List;
 ​
 /**
  * @Author: lijiahao
  * @Description:
  * @Data: Create in 21:37 2020/2/22
  * @Modified By:
  */
 public class User implements Serializable {
     private Integer id;
     private String username;
     private Date birthday;
     private String sex;
     private String address;
 ​
     //一对多关系映射,主表实体应该包含从表实体的集合引用
     private List<Account> accounts;
 ​
     public List<Account> getAccounts() {
         return accounts;
    }
 ​
     public void setAccounts(List<Account> accounts) {
         this.accounts = accounts;
    }
 ​
     public Integer getId() {
         return id;
    }
 ​
     public void setId(Integer id) {
         this.id = id;
    }
 ​
     public String getUsername() {
         return username;
    }
 ​
     public void setUsername(String username) {
         this.username = username;
    }
 ​
     public Date getBirthday() {
         return birthday;
    }
 ​
     public void setBirthday(Date birthday) {
         this.birthday = birthday;
    }
 ​
     public String getSex() {
         return sex;
    }
 ​
     public void setSex(String sex) {
         this.sex = sex;
    }
 ​
     public String getAddress() {
         return address;
    }
 ​
     public void setAddress(String address) {
         this.address = address;
    }
 ​
     @Override
     public String toString() {
         return "User{" +
                 "id=" + id +
                 ", username='" + username + '\'' +
                 ", birthday=" + birthday +
                 ", sex='" + sex + '\'' +
                 ", address='" + address + '\'' +
                 '}';
    }
 }
用户映射配置文件IUserDao.xml
 <?xml version="1.0" encoding="utf-8" ?>
 <!DOCTYPE mapper
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 ​
 <mapper namespace="com.itheima.dao.IUserDao">
 ​
     <!--定义user的resultMap user为主表,account为从表,构成一对多关系-->
     <resultMap id="userAccountMap" type="user">
         <id property="id" column="id"></id>
         <result property="username" column="username"></result>
         <result property="address" column="address"></result>
         <result property="sex" column="sex"></result>
         <result property="birthday" column="birthday"></result>
         <!--配置user对象中accounts集合的映射
    select 后面即为延迟 后的查询语句,根据user中的id查询-->
         <collection property="accounts" ofType="account" select="com.itheima.dao.IAccountDao.findAccountByUid" column="id">
         </collection>
     </resultMap>
     <select id="findAll" resultMap="userAccountMap">
         select * from user
     </select>
 ​
     <!--根据id查找一个用户的信息-->
     <select id="findById" parameterType="INT" resultType="user">
         select * from user where id = #{userid}
     </select>
 ​
 </mapper>
测试类
 package com.itheima;
 ​
 import com.itheima.dao.IUserDao;
 import com.itheima.domain.User;
 import org.apache.ibatis.io.Resources;
 import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSessionFactory;
 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 ​
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
 ​
 /**
  * @Author: lijiahao
  * @Description:
  * @Data: Create in 22:56 2020/2/22
  * @Modified By:
  */
 public class UserTest {
 ​
     private InputStream in;
     private SqlSession sqlSession;
     private IUserDao userDao;
 ​
     @Before
     public void init() throws IOException {
         //1.读取配置文件
         in = Resources.getResourceAsStream("SqlMapConfig.xml");
         //2.创建SqlSessionFactory工厂
         SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
         SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(in);
         sqlSession = sqlSessionFactory.openSession(true);
         //3.使用工厂生产dao对象
         userDao = sqlSession.getMapper(IUserDao.class);
    }
 ​
     @After
     public void destory() throws IOException {
         in.close();
    }
 ​
     @Test
     public void testFindAll() throws IOException {
         //5.使用代理对象执行方法
         List<User> users = userDao.findAll();
         for (User user : users) {
             System.out.println(user);
             System.out.println(user.getAccounts());
        }
    }
 ​
 }

Mybatis的延迟加载和立即加载的更多相关文章

  1. Mybatis源码解析(二) —— 加载 Configuration

    Mybatis源码解析(二) -- 加载 Configuration    正如上文所看到的 Configuration 对象保存了所有Mybatis的配置信息,也就是说mybatis-config. ...

  2. Hibernate之加载策略(延迟加载与即时加载)和抓取策略(fetch)

    假设现在有Book和Category两张表,表的关系为双向的一对多,表结构如下: 假设现在我想查询id为2的那本书的书名,使用session.get(...)方法: Session session=H ...

  3. EF如何操作内存中的数据以及加载相关联表的数据:延迟加载、贪婪加载、显示加载

    之前的EF Code First系列讲了那么多如何配置实体和数据库表的关系,显然配置只是辅助,使用EF操作数据库才是每天开发中都需要用的,这个系列讲讲如何使用EF操作数据库.老版本的EF主要是通过Ob ...

  4. EF 延迟加载和预先加载

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精   本节探讨延迟加载和预先加载 Entity Frame ...

  5. Entity Framework关联查询以及数据加载(延迟加载,预加载)

    数据加载分为延迟加载和预加载 EF的关联实体加载有三种方式:Lazy Loading,Eager Loading,Explicit Loading,其中Lazy Loading和Explicit Lo ...

  6. EF如何操作内存中的数据和加载外键数据:延迟加载、贪婪加载、显示加载

    EF如何操作内存中的数据和加载外键数据:延迟加载.贪婪加载.显示加载 之前的EF Code First系列讲了那么多如何配置实体和数据库表的关系,显然配置只是辅助,使用EF操作数据库才是每天开发中都需 ...

  7. 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性)

    一. 简介 上一个章节中,也介绍了立即加载和延迟加载,但上一个章节是针对单表而言的,不含外键,立即也好,延迟也好,都是指单表中的数据.但本章节重点介绍的三种加载方式均是针对含(导航属性.外键)的情况下 ...

  8. ASP.NET MVC深入浅出(被替换) 第一节: 结合EF的本地缓存属性来介绍【EF增删改操作】的几种形式 第三节: EF调用普通SQL语句的两类封装(ExecuteSqlCommand和SqlQuery ) 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性) 第十节: EF的三种追踪

    ASP.NET MVC深入浅出(被替换)   一. 谈情怀-ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态 ...

  9. NHibernate 延迟加载与立即加载 (第七篇)

    NHibernate 延迟加载与立即加载 (第七篇) 一.延迟加载 延迟加载可以理解为:当需要用的时候才加载. 假设我们数据库有一个Person对象,一个Country对象,其中Person属于Cou ...

随机推荐

  1. conCat()的应用

    编写一个Java应用程序,从键盘读取用户输入两个字符串,并重载3个函数分别实现这两个字符串的拼接.整数相加和浮点数相加.要进行异常处理,对输入的不符合要求的字符串提示给用户: package com. ...

  2. 使用CStatic显示图片(bmp、ico、png)

    一.显示bmp及ico //h文件 CStatic m_static; //cpp文件 CBitmap bitmap; bitmap.LoadBitmapW(IDB_BITMAP); //加载位图 B ...

  3. 《Python学习手册 第五版》 -第12章 if测试和语法规则

    本章节的内容,主要讲解if语句,if语句是三大复合语句之一(其他两个是while和for),能处理编程中大多数逻辑运算 本章的重点内容如下: 1.if语句的基本形式(多路分支) 2.布尔表达式 3.i ...

  4. tomcat-windows10环境搭建

    1.进入Tomcat官网Apache Tomcat® - Welcome! 2.根据操作系统选择合适的版本下载 zip用于windows操作系统, tar.gz用于unix和linux操作系统 Bin ...

  5. 一口气说出Redis 5种数据结构及对应使用场景,面试要加分的

    整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 更多优选 一口气说出 9种 分布式ID生成方式,面试官有点懵了 ...

  6. num06---代理模式

    代理模式,比较好理解,关键点就是,被代理类 和 代理类 实现同一个接口,接口中定义着想要实现的被代理的方法,在代理类中引入 被代理类 对象, 最后直接调用代理类的方法即可实现代理功能.

  7. Go语言实现:【剑指offer】连续子数组的最大和

    该题目来源于牛客网<剑指offer>专题. HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向 ...

  8. 【Debian】 Debian 安装源配置

    Debian 安装源配置 所有的Linux安装完后第一件事,就是要更新安装源 安装源是什么呢,安装源又称软件源,是指把软件的安装源地址放在一个pool里面,用一条命令(比如apt-get instal ...

  9. pytorch --Rnn语言模型(LSTM,BiLSTM) -- 《Recurrent neural network based language model》

    论文通过实现RNN来完成了文本分类. 论文地址:88888888 模型结构图: 原理自行参考论文,code and comment: # -*- coding: utf-8 -*- # @time : ...

  10. python 安装自己下载的whl依赖

    下载好之后保存到相应的地方,如下载了xxxx.whl文件并将它保存在D:\python\project目录下,然后 pip install  D:\python\project\xxxx.whl即可