mybatis中的消極式載入,mybatis消極式載入
一、消極式載入
resultMap可以實現進階映射(使用association、collection實現一對一及一對多映射),association、collection具備消極式載入功能。
消極式載入:先從單表查詢,需要時再從關聯表去關聯查詢,大大提高資料庫效能,因為查詢單表要比關聯查詢多張錶速度要快。
在mybatis核心設定檔中配置:
lazyLoadingEnabled、aggressiveLazyLoading
設定項 |
描述 |
允許值 |
預設值 |
lazyLoadingEnabled |
全域性設定懶載入。如果設為‘false’,則所有相關聯的都會被初始化載入。 |
true | false |
false |
aggressiveLazyLoading |
當設定為‘true’的時候,懶載入的對象可能被任何懶屬性全部載入。否則,每個屬性都按需載入。 |
true | false |
true |
<settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/></settings>
場合:
當只有部分記錄需要關聯查詢其它資訊時,此時可按需消極式載入,需要關聯查詢時再向資料庫發出sql,以提高資料庫效能。
當全部需要關聯查詢資訊時,此時不用消極式載入,直接將關聯查詢資訊全部返回即可,可使用resultType或resultMap完成映射。
二:案例:(在部門和員工一對多)
源碼介紹:
1.Dept.java
package cn.zhang.entity;import java.util.HashSet;import java.util.Set;public class Dept { private Integer deptno; private String deptname; private Set<Emp> emp = new HashSet<Emp>(); @Override public String toString() { return "Dept [deptno=" + deptno + ", deptname=" + deptname + ", emp=" + emp + "]"; } public Integer getDeptno() { return deptno; } public void setDeptno(Integer deptno) { this.deptno = deptno; } public String getDeptname() { return deptname; } public void setDeptname(String deptname) { this.deptname = deptname; } public Set<Emp> getEmp() { return emp; } public void setEmp(Set<Emp> emp) { this.emp = emp; }}
View Code
2.Emp.java
package cn.zhang.entity;public class Emp { private Integer empno; private String empname; @Override public String toString() { return "Emp [empno=" + empno + ", empname=" + empname + "]"; } public Integer getEmpno() { return empno; } public void setEmpno(Integer empno) { this.empno = empno; } public String getEmpname() { return empname; } public void setEmpname(String empname) { this.empname = empname; } }
View Code
3.MybatisUtil.java
package cn.zhang.util;import java.io.IOException;import java.io.Reader;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;/** * 工具類 * */public class MybatisUtil { private static String config = "mybatis-config.xml"; static Reader reader; static { try { reader = Resources.getResourceAsReader(config); } catch (IOException e) { e.printStackTrace(); } } private static SqlSessionFactory factory = new SqlSessionFactoryBuilder() .build(reader); // 提供一個可以擷取到session的方法 public static SqlSession getSession() throws IOException { SqlSession session = factory.openSession(); return session; }}
View Code
4.DeptDao.java
package cn.zhang.dao;import java.io.IOException;import cn.zhang.entity.Dept;public interface DeptDao { /** * 查詢指定記錄 * @return * @throws IOException */ public Dept findById(Integer id) throws IOException;}
View Code
5.DeptDAO.xml
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="cn.zhang.dao.DeptDao"> <!-- 3.根據員工id查詢員工資訊 --> <select id="selectEmpByDeptNo" resultType="Emp"> select empno,empname from emp where deptno=#{deptno} </select> <!-- 2.對部門實體的映射 --> <resultMap type="Dept" id="deptMapper"> <id property="deptno" column="deptno" /> <result property="deptname" column="deptname" /> <!-- 一對多部門關聯的員工 --> <!--select:關聯員工查詢 --> <!--column:關聯員工查詢所需要的條件(來源於1) --> <collection property="emp" ofType="Emp" select="selectEmpByDeptNo" column="deptno" /> </resultMap> <!--1.根據部門id查詢部門資訊 --> <select id="findById" resultMap="deptMapper"> select deptno,deptname from dept where deptno=#{deptno} </select></mapper>
View Code
6.mybatis-config.xml (消極式載入的配置在此)
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration> <!--lazyLoadingEnabled:設定懶載入,預設為false。如果為false:則所有相關聯的都會被初始化載入。 aggressiveLazyLoading:預設為true。當設定為true時,懶載入的對象可能被任何懶屬性全部載入;否則,每個屬性按需載入。 --> <settings> <!-- 開啟消極式載入的開關 --> <setting name="lazyLoadingEnabled" value="true" /> <!-- 將積極載入改為訊息載入即按需載入 --> <setting name="aggressiveLazyLoading" value="false" /> </settings> <!-- 配置別名 --> <typeAliases> <!--方式一: 按類型名定製別名 --> <!--方式二: 拿當前指定包下的簡單類名作為別名 --> <package name="cn.zhang.entity" /> </typeAliases> <environments default="oracle"> <environment id="oracle"> <!-- 使用jdbc的事務 --> <transactionManager type="JDBC" /> <!-- 使用內建的串連池 --> <dataSource type="POOLED"> <!-- 我用的Oracle資料庫 --> <property name="driver" value="oracle.jdbc.driver.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl" /> <property name="username" value="study" /> <property name="password" value="123" /> </dataSource> </environment> </environments> <mappers> <mapper resource="cn/zhang/dao/DeptDAO.xml" /> </mappers></configuration>
View Code
7.MyTest.java(測試類別)
package cn.zhang.test;//一對多import java.io.IOException;import org.apache.ibatis.session.SqlSession;import org.junit.Before;import org.junit.Test;import cn.zhang.dao.DeptDao;import cn.zhang.entity.Dept;import cn.zhang.util.MybatisUtil;public class MyTest { DeptDao dao; @Before public void initData() throws IOException{ SqlSession session = MybatisUtil.getSession(); dao = session.getMapper(DeptDao.class); } /** * 查詢指定記錄 * @throws IOException */ @Test public void findAll() throws IOException{ Dept dept = dao.findById(1); System.out.println(dept); }}
View Code測試結果:
在下面位置打斷點
情況一:在mybatis-config.xml中不做配置情況
情況二:在mybatis-config.xml中配置
<settings> <!-- 開啟消極式載入的開關 --> <setting name="lazyLoadingEnabled" value="true" /> <!-- 將積極載入改為訊息載入即按需載入 --> <setting name="aggressiveLazyLoading" value="false" /></settings>
下一步:
F6下步:
F6下步:打出員工的名字
情況三:
F6下一步:
F6下一步:列印出員工名字