Mybatis延迟加载

在多表关联查询时,可以通过association加载关联方数据,例如通过findById加载指定Student后,继续对应的加载Classes数据。如果有一种需求,查询student时,只加载该student数据,只有需要加载对应的classes时,例如调用student.getClasses(),此时mybatis框架采取执行加载对应classes的操作,这就叫延迟加载。

延迟加载步骤

  • 在config.xml中开启延迟加载

    <settings>
    <!--打印日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    <!--开启延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>
    
  • 将多表关联查询拆分成单表查询

    1. ClassesRepository.java

      package com.simon.app.repository;
      
      import com.simon.app.entity.Classes;
      
      public interface ClassesRepository {
          public Classes findById(long id);
      }
      
      
    2. ClassesRepository.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.simon.app.repository.ClassesRepository">
          <resultMap id="classesMap" type="com.simon.app.entity.Classes">
             <id column="id" property="id"></id>
              <result column="name" property="name"></result>
          </resultMap>
          <select id="findById" parameterType="long" resultMap="classesMap">
              select id,name from classes where id=#{id}
          </select>
      </mapper>
      
    3. StudentRepository.java

      package com.simon.app.repository;
      
      import com.simon.app.entity.Student;
      
      public interface StudentRepository {
          public Student findById(long id);
      }
      
      
    4. StudentRepository.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.simon.app.repository.StudentRepository">
          <resultMap id="studentMap" type="com.simon.app.entity.Student">
             <id column="id" property="id"></id>
              <result column="name" property="name"></result>
              <association property="classes" javaType="com.simon.app.entity.Classes" select="com.simon.app.repository.ClassesRepository.findById" column="cid">
              </association>
          </resultMap>
          <select id="findById" parameterType="long" resultMap="studentMap">
              select id,name,cid from student where id=#{id}
          </select>
      </mapper>
      
      • 第11行只是进行简单的student查询
      • association标签中增加了select属性,也就是说student中的classes属性值是通过ClassesRepository接口的findById进行读取,而该findById的参数是通过column属性获取的,而值就是查询student的sql语句中的字段名
    5. 测试

      package test;
      
      import com.simon.app.entity.Student;
      import com.simon.app.repository.StudentRepository;
      import org.apache.ibatis.session.SqlSession;
      import org.apache.ibatis.session.SqlSessionFactory;
      import org.apache.ibatis.session.SqlSessionFactoryBuilder;
      
      import java.io.InputStream;
      
      public class Test {
          public static void main(String[] args) {
              InputStream resource = Test.class.getClassLoader().getResourceAsStream("config.xml");
              SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
              SqlSessionFactory factory = sqlSessionFactoryBuilder.build(resource);
              SqlSession sqlSession = factory.openSession();
              //获取接口的代理对象
              StudentRepository mapper = sqlSession.getMapper(StudentRepository.class);
      
              Student student = mapper.findById(1L);
              System.out.println(student.getName());
              sqlSession.close();
          }
      }
      
      

      执行后可以看到只加载了student部分,关联的classes为null,控制台上可以看见只发出了一条查询student的sql语句。

      如果此时需要读取该student关联的classes,可以在20行后增加如下语句

      System.out.println(student.getClasses());
      

      执行后就会发现控制台连续发出了两条sql语句,延迟加载成功。

      注意:平常习惯性的写下面的语句

      System.out.println(student)
      

      结果总是发出两条sql分别查询student和classes,还以为延迟加载失败了,其实也可以理解,因为直接打印student,肯定会发出查询关联的classes的命令,如果只显示student自身的属性就不会出现以上情况,所以要加以注意。

posted @ 2021-10-03 11:59  疯狗强尼  阅读(52)  评论(0编辑  收藏  举报