MyBatis懒加载(延迟加载)

懒加载(延迟加载)

需要查询关联信息时,使用 Mybatis 懒加载特性可有效的减少数据库压力,首次查询只查询主表信息,关联表的信息在用户获取时再加载。

Mybatis 一对一关联的 association 和一对多的 collection 可以实现懒加载。懒加载时要使用 resultMap,不能使用 resultType。

启动懒加载
Mybatis 默认没有打开懒加载配置,需要在 SqlMapperConfig.xml 中通过settings 配置 lazyLoadingEnabled 来开启懒加载。

<settings>
	<setting name="lazyLoadingEnabled" value="true"/>
settings>

我们建立一个实例来体现懒加载,体现懒加载的优势
创建一个方法用来创建SqlSessionFactory负责创建每次会话

package com.util;

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 java.io.IOException;
import java.io.InputStream;

public class SqlSessionUtil {
     
    static SqlSessionFactory sqlSessionFactory;

    static {
     
        //读取mybatis配置文件信息

        try {
     
           InputStream in = Resources.getResourceAsStream("myBatis-configer.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);

        } catch (IOException e) {
     
            e.printStackTrace();
        }
        //创建SqlSessionFactory负责创建每次会话的sqlSession==connection
        //创建开销比较大,所以整个应用程序只需要创建一个

    }

    public static SqlSession getSqlSession() {
     
        return sqlSessionFactory.openSession();
    }
}

我们创建个bean类

package com.pojo;
//一个emp员工类
public class Emp {
     
    private int id;
    private String name;
    private int age;
    private Dept dept;

    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 int getAge() {
     
        return age;
    }

    public void setAge(int age) {
     
        this.age = age;
    }

    public Dept getDept() {
     
        return dept;
    }

    public void setDept(Dept dept) {
     
        this.dept = dept;
    }
}
package com.pojo;

import java.util.List;

public class Dept {
     
    private int id;
    private String name;
    private List<Emp> empList;

    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 List<Emp> getEmpList() {
     
        return empList;
    }

    public void setEmpList(List<Emp> empList) {
     
        this.empList = empList;
    }
}

empDao接口

package com.dao;

import com.ff.pojo.Emp;
import org.apache.ibatis.annotations.Param;

public interface EmpDao {
     

    //    延迟加载
    Emp findEmpById1(@Param("id") int id);
}

EmpMapper.xml


DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dao.EmpDao">
 
    
    <resultMap id="EmpMap1" type="Emp">
        <id property="id" column="id">id>
        <result property="name" column="name">result>
        <result property="age" column="age">result>
         
        <association property="dept" javaType="Dept"
                     select="findDeptById" fetchType="lazy" column="dept_id">
            <id property="id" column="id">id>
            <result property="name" column="name">result>
        association>
    resultMap>
    <select id="findEmpById1" resultMap="EmpMap1">
        select id,name,age,dept_id,user_id from emp where id = #{id}
    select>
    <select id="findDeptById" resultType="Dept">
        select id,name from dept where id = #{id}
    select>

mapper>
package com.ff.test;

import com.ff.dao.EmpDao;
import com.ff.dao.UserDao;
import com.ff.pojo.Dept;
import com.ff.pojo.Emp;
import com.ff.util.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class emp {
     
    @Test
    public void findEmpById() throws IOException {
     
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
        empDao.findEmpById(1);
        sqlSession.commit();
        sqlSession.close();
    }
}

非懒加载查询情况

他会将两个表关联查询,所有的信息全部加载出来

Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 396883763.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@17a7f733]
==>  Preparing: SELECT e.id eId, e.name eName, e.age, d.id dId, d.name dName/*, u.id uId, u.user_name uName*/ FROM emp e LEFT JOIN dept d ON e.dept_id = d.id /*LEFT JOIN USER u ON e.user_id = u.id*/ WHERE e.id = ? 
==> Parameters: 1(Integer)
<==    Columns: eId, eName, age, dId, dName
<==        Row: 1, 小崔, 20, 1, 科技部
<==      Total: 1
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@17a7f733]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@17a7f733]
Returned connection 396883763 to pool.

Process finished with exit code 0

懒加载查询情况

我们创建一个test方法,用来调用service中的方法

package com.test;

import com.ff.dao.EmpDao;
import com.ff.pojo.Dept;
import com.ff.pojo.Emp;
import com.ff.util.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class emp {
     
   
    @Test
    public void findEmpById() throws IOException {
     
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        EmpDao empDao = sqlSession.getMapper(EmpDao.class);

        //延迟加载
        Emp emp = empDao.findEmpById1(2);
        System.out.println(emp.getName());

        //如果不调用emp中的关于Dept的方法,就不会查询部门信息,只会查询emp的数据库信息
        System.out.println("__________________________________");
        System.out.println(emp.getDept().getName());

        sqlSession.close();
    }
}

运行结果

Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 396883763.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@17a7f733]
==>  Preparing: select id,name,age,dept_id from emp where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, name, age, dept_id
<==        Row: 1, 小崔, 20, 1
<==      Total: 1
小崔
__________________________________
==>  Preparing: select id,name from dept where id = ? 
==> Parameters: 1(Integer)
<==    Columns: id, name
<==        Row: 1, 科技部
<==      Total: 1
科技部
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@17a7f733]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@17a7f733]
Returned connection 396883763 to pool.

Process finished with exit code 0

我们会发现,只有需要部门信息 的时候他才会查询,两张表上的信息他是分两次查询,这样就减少了数据库的开销

你可能感兴趣的:(spring框架,JAVA,数据库,mybatis,mysql,新星计划)