Mybatis的延遲加載

在實際開發中,有的數據不需要立即加載,而是需要的時候再去加載,不需要用到的時候則不去加載,這就是延時加載,也稱爲按需加載(懶加載)

  • 利 : 提高數據庫性能 
    弊 : 需要時候在查詢,存在大批量的數據查詢。
    

assocation的延時加載

要求:查詢賬戶信息,同時按需加載用戶信息。

  1. 創建實體類
package com.liang.domain;

import java.io.Serializable;

/**
 * 賬戶實體類
 */
public class Account implements Serializable {

    private int id;
    private int uid;
    private Double money;

    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public int getId() {
        return id;
    }

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

    public int getUid() {
        return uid;
    }

    public void setUid(int 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 +
                '}';
    }
}
package com.liang.domain;

import java.util.Date;

/**
 * 用戶類
 */
public class User {

    private int id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public int getId() {
        return id;
    }

    public void setId(int 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 + '\'' +
                '}';
    }
}
  1. 創建持久層接口
package com.liang.dao;

import com.liang.domain.Account;

import java.util.List;

/**
 * 賬戶的持久層接口
 */
public interface AccountDao {

    /**
     * 查詢所有賬戶信息,同時包含其用戶信息
     * @return
     */
    List<Account> findAll();
}
package com.liang.dao;

public interface UserDao{

  /**
     * 根據id查詢用戶
     * @param id
     * @return
     */
    User findById(int id);
}
  1. 編寫持久層映射文件
 <resultMap id="accountMap" type="com.liang.domain.Account">
        <id property="id" column="id"></id>
        <result column="uid" property="uid"></result>
        <result column="money" property="money"></result>
        <!--建立Account類中user屬性對應的數據庫表
        column:	數據庫中的列名,或者是列的別名。一般情況下,是我們傳遞給select映射的參數
        select: 用於加載複雜類型屬性的映射語句的 ID,它會從 column 屬性指定的列中檢索數據,作爲參數傳遞給目標 select 語句。
        -->
        <association property="user" javaType="com.liang.domain.User" select="com.liang.dao.UserDao.findById" column="uid">
        </association>
    </resultMap>
    <!--查詢所有賬戶信息,同時包含其用戶信息-->
    <select id="findAll" resultMap="accountMap">
       select *from account;
    </select>
   <!--根據id查詢用戶-->
    <select id="findById" resultType="User" parameterType="int">
        <include refid="querySql"></include> where id= #{userID};
    </select>
  1. 編寫測試方法
   /**
     * 查詢所有賬戶信息,同時包含其用戶信息【延遲加載】
     */
    @Test
    public void testFindAll()
    {
        List<Account> accounts = accountDao.findAll();
    }
  1. 開啓延遲加載策略
  <settings>
        <!--
            lazyLoadingEnabled : 延遲加載的全局開關。當開啓時,所有關聯對象都會延遲加載。
            aggressiveLazyLoading : 當開啓時,任何方法的調用都會加載該對象的所有屬性
        -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

此時執行程序的日誌爲:
在這裏插入圖片描述
而當沒有延時加載時,程序執行日誌爲:
在這裏插入圖片描述
可以看出:當沒有延時加載時候,採用的是立即加載策略。

collection的延時加載

要求:查詢用戶信息,同時按需加載賬戶信息。

  1. 編寫實體類
package com.liang.domain;

import java.util.Date;
import java.util.List;

/**
 * 用戶類
 */
public class User {

    private int 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 int getId() {
        return id;
    }

    public void setId(int 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 + '\'' +
                '}';
    }
}
package com.liang.domain;

import java.io.Serializable;

/**
 * 賬戶實體類
 */
public class Account implements Serializable {

    private int id;
    private int uid;
    private Double money;

    public int getId() {
        return id;
    }

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

    public int getUid() {
        return uid;
    }

    public void setUid(int 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 +
                '}';
    }
}
  1. 編寫持久層接口類方法
package com.liang.dao;

import com.liang.domain.User;

import java.util.List;

public interface UserDao{


    /**
     * 查詢所有用戶
     * @return
     */
    List<User> findAll();

}
package com.liang.dao;

import com.liang.domain.Account;

import java.util.List;

/**
 * 賬戶的持久層接口
 */
public interface AccountDao {

    /**
     * 通過用戶id查詢賬戶信息
     * @param uid
     * @return
     */
    List<Account> findByUid(int uid);
}
  1. 編寫持久層映射文件
<?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.liang.dao.UserDao">

    <resultMap id="userMap" type="com.liang.domain.User">
        <id column="id" property="id"></id>
        <result property="username" column="username"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
        <result property="birthday" column="birthday"></result>
        <collection property="accounts" select="com.liang.dao.AccountDao.findByUid" column="id"></collection>
    </resultMap>
    <select id="findAll" resultMap="userMap">
            select *from user;
    </select>
</mapper>
<?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.liang.dao.AccountDao">

    <select id="findByUid" parameterType="int" resultType="com.liang.domain.Account">
        select *from account where uid = #{uid}
    </select>

</mapper>
  1. 編寫測試方法
import com.liang.dao.UserDao;
import com.liang.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;

public class TestMyBatis {

    private SqlSession sqlSession = null;
    private InputStream inputStream = null;
    private UserDao userDao = null;

    @Before
    public void init() throws IOException {
        inputStream = Resources.getResourceAsStream("SqlConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        sqlSession = sqlSessionFactory.openSession();
        userDao = sqlSession.getMapper(UserDao.class);
    }

    @After
    public void destroy() throws IOException {

        sqlSession.commit();

        sqlSession.close();
        inputStream.close();
    }

    /**
     * 查詢所有用戶信息
     */
    @Test
    public void testFindAll() {
        List<User> users = userDao.findAll();
    } 
}
  1. 開啓延遲加載策略
  <settings>
        <!--
            lazyLoadingEnabled : 延遲加載的全局開關。當開啓時,所有關聯對象都會延遲加載。
            aggressiveLazyLoading : 當開啓時,任何方法的調用都會加載該對象的所有屬性
        -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

經測試,開啓延時加載時,程序執行日誌爲:
在這裏插入圖片描述

發佈了71 篇原創文章 · 獲贊 6 · 訪問量 5385
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章