Mybatis的延遲加載

Mybatis的延遲加載

?一、什么是延遲加載

延遲加載:  就是在需要用到數(shù)據(jù)時才進行加載,不需要用到數(shù)據(jù)時就不加載數(shù)據(jù)。延遲加載也稱懶加載.好處:  先從單表查詢,需要時再從關(guān)聯(lián)表去關(guān)聯(lián)查詢,大大提高數(shù)據(jù)庫性能,因為查詢單表要比關(guān)聯(lián)查詢多張表速度要快。壞處:  因為只有當(dāng)需要用到數(shù)據(jù)時,才會進行數(shù)據(jù)庫查詢,這樣在大批量數(shù)據(jù)查詢時,因為查詢工作也要消耗時間,所以可能造成用戶等待時間變長,造成用戶體驗下降。

二、實現(xiàn)需求

需求:  查詢賬戶(Account)信息并且關(guān)聯(lián)查詢用戶(User)信息。如果先查詢賬戶(Account)信息即可滿足要求,當(dāng)我們需要查詢用戶(User)信息時再查詢用戶(User)信息。把對用戶(User)信息的按需去查詢就是延遲加載?! ssociation、collection 具備延遲加載功能。

三、使用association實現(xiàn)延遲加載  

需求:

查詢賬戶信息同時查詢用戶信息。

3.1 賬戶的持久層dao接口

package com.llb.dao;import com.llb.domain.Account;import java.util.List;/** * Ceate By llb on 2019/8/7

*/publicinterface AccountMapper {


? ? /**? ? * 查詢賬戶所對應(yīng)的的用戶

? ? */? ? List findAccountAndUser();

}

3.2 賬戶的持久層映射文件

<?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.llb.dao.AccountMapper">

????<!--定義封裝account和user的resultMap-->

????<resultMap id="accountMap" type="com.llb.domain.Account">

????????<id property="id" column="id"></id>

????????<result property="uid" column="uid"></result>

????????<result property="money" column="money"></result>

????????<!--一對一的關(guān)系映射 JavaType:對應(yīng)的是哪個類 select 指定的內(nèi)容:查詢用戶的唯一標(biāo)識 -->

????????<association property="user" column="uid" javaType="com.llb.domain.User" select="com.llb.dao.UserMapper.findById" ></association> ????</resultMap>

????<select id="findAccountAndUser" resultMap="accountMap"> select * from account </select>

</mapper>

3.3 用戶的持久層接口

package com.llb.dao;import com.llb.domain.User;import java.util.List;/** * 用戶的持久層接口

* Ceate By llb on 2019/8/5

*/publicinterface UserMapper {


? ? /**? ? * 根據(jù)id查詢所有用戶

? ? * @return*/? ? User findById(Integer id);

? ? /**? ? * 查詢出所有用戶,包含賬戶信息

? ? * @return*/? ? List findAccountAndUser();

}

3.4 用戶的持久層映射文件

<?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.llb.dao.UserMapper">? ?

????<!--配置 查詢結(jié)果的列名和實體類的屬性名的對應(yīng)關(guān)系-->? ?

????<resultMap id="userMap" type="com.llb.domain.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集合的映射? ? ? ofType:表示集合的類型-->? ? ? ?

????????<collection property="accounts" ofType="com.llb.domain.Account">? ? ? ? ? ?

????????????<id property="id" column="aid"></id>? ? ? ? ? ?

????????????<result property="uid" column="uid"></result>? ? ? ? ? ?

????????????<result property="money" column="money"></result>? ? ? ?

????????????</collection>? ?????????

????</resultMap>? ? <!--查詢出用戶所對應(yīng)的賬戶-->? ?

<select id="findAccountAndUser" resultMap="userMap">? ? ? ? select * from user left outer join account on user.id = account.uid? ? </select>? ? <!--根據(jù)id查詢用戶-->? ? <select id="findById" resultType="user" parameterType="int">? ? ? ? select * from user where id = #{id}? ? </select></mapper>


3.5 開啟mybatis的延遲加載策略

進入 Mybaits 的官方文檔,找到 settings 的說明信息:


我們需要在 Mybatis 的配置文件 SqlMapConfig.xml 文件中添加延遲加載的配置。

? ? <!--配置參數(shù),延遲加載-->

? ? <settings>

? ? ? ? <!--開啟mybatis支持延遲加載-->

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

? ? ? ? <!--不配置也可以:默認為false;允許觸發(fā)方法進行延遲加載,否則立即加載-->

? ? ? ? <setting name="aggressiveLazyLoading" value="false"></setting>

? ? </settings>

3.6 編寫測試只查賬戶信息不查用戶信息

*/publicclass AccountTest {

? ? InputStream in =null;

? ? AccountMapper mapper =null;

? ? SqlSession sqlSession =null;

? ? /**? ? * 在測試方法執(zhí)行前執(zhí)行

? ? * @throws IOException

? ? */? ? @Before

? ? publicvoidinit()throws IOException {

? ? ? ? //1.讀取配置文件,生成字節(jié)流in = Resources.getResourceAsStream("SqlMapConfig.xml");

? ? ? ? //2.獲取sqlSessionFactory對象SqlSessionFactory factory =new SqlSessionFactoryBuilder().build(in);

? ? ? ? //3.獲取sqlSession對象sqlSession = factory.openSession();

? ? ? ? //4.獲取dao的代理對象mapper = sqlSession.getMapper(AccountMapper.class);

? ? }

? ? /**? ? * 測試方法執(zhí)行后執(zhí)行

? ? * @throws IOException

? ? */? ? @After

? ? publicvoiddestory()throws IOException {

? ? ? ? sqlSession.commit();

? ? ? ? //6.釋放資源? ? ? ? sqlSession.close();

? ? ? ? in.close();

? ? }

? ? /**? ? * 查詢出賬戶所對應(yīng)的user

? ? */? ? @Test

? ? publicvoid testFindAccountAndUser(){

? ? ? ? List accountUser = mapper.findAccountAndUser();//? ? ? ? for (Account account: accountUser) {//? ? ? ? ? ? System.out.println(account);//? ? ? ? }? ? }

}


3.7 測試結(jié)果

當(dāng)不進行配置時,立即加載,查詢account所對應(yīng)的user,一起將user查詢出來:

  配置后,對account進行查詢放入到list集合中,并沒有涉及到user對象,所以就沒有發(fā)出 SQL 語句查詢賬戶所關(guān)聯(lián)的 User 對象的查詢。:

四、使用collection實現(xiàn)緩存策略

同樣我們也可以在一對多關(guān)系配置的<collection>結(jié)點中配置延遲加載策略。

<collection>結(jié)點中也有 select 屬性,column 屬性。

需求:

????完成加載用戶對象時,查詢該用戶所擁有的賬戶信息。

4.1 在User實體類中加入List<Account>屬性

package com.llb.domain;import java.io.Serializable;

import java.util.Date;import java.util.List;/** * Ceate By llb on 2019/8/5

*/publicclassUserimplements Serializable{

? ? private Integer id;

? ? private String username;

? ? private String address;

? ? private String sex;

? ? private Date birthday;

? ? //一對多關(guān)系。一的方包含多的一方所有對象privateList accounts;

? ? @Override

? ? public String toString() {

? ? ? ? return"User{" +? ? ? ? ? ? ? ? "id=" + id +? ? ? ? ? ? ? ? ", username='" + username + '\'' +? ? ? ? ? ? ? ? ", address='" + address + '\'' +? ? ? ? ? ? ? ? ", sex='" + sex + '\'' +? ? ? ? ? ? ? ? ", birthday=" + birthday +? ? ? ? ? ? ? ? ", accounts=" + accounts +? ? ? ? ? ? ? ? '}';

? ? }

? ? publicList getAccounts() {

? ? ? ? return accounts;

? ? }

? ? publicvoidsetAccounts(List accounts) {

? ? ? ? this.accounts = accounts;

? ? }

? ? public Integer getId() {

? ? ? ? return id;

? ? }

? ? publicvoid setId(Integer id) {

? ? ? ? this.id = id;

? ? }

? ? public String getUsername() {

? ? ? ? return username;

? ? }

? ? publicvoid setUsername(String username) {

? ? ? ? this.username = username;

? ? }

? ? public String getAddress() {

? ? ? ? return address;

? ? }

? ? publicvoid setAddress(String address) {

? ? ? ? this.address = address;

? ? }

? ? public String getSex() {

? ? ? ? return sex;

? ? }

? ? publicvoid setSex(String sex) {

? ? ? ? this.sex = sex;

? ? }

? ? public Date getBirthday() {

? ? ? ? return birthday;

? ? }

? ? publicvoid setBirthday(Date birthday) {

? ? ? ? this.birthday = birthday;

? ? }

}

4.2 編寫用戶接口和配置文件

UserMapper.class:

package com.llb.dao;import com.llb.domain.User;import java.util.List;/** * 用戶的持久層接口

* Ceate By llb on 2019/8/5

*/publicinterface UserMapper {

? ? /**? ? * 根據(jù)id查詢所有用戶

? ? * @return*/? ? User findById(Integer id);

? ? /**? ? * 查詢出所有用戶,包含賬戶信息

? ? * @return*/? ? List findAccountAndUser();

}

UserMapper.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.llb.dao.UserMapper">

<!--配置 查詢結(jié)果的列名和實體類的屬性名的對應(yīng)關(guān)系-->

<resultMap id="userMap" type="com.llb.domain.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集合的映射 ofType:表示集合的類型-->

????<collection property="accounts" ofType="com.llb.domain.Account" select="com.llb.dao.AccountMapper.findAccountById" column="id"> </collection>

</resultMap> <!--查詢出用戶所對應(yīng)的賬戶-->

????<select id="findAccountAndUser" resultMap="userMap">

????????select * from user

????</select>

????<!--根據(jù)id查詢用戶-->

????<select id="findById" resultType="user" parameterType="int">

????????select * from user where id = #{id}

????</select>

</mapper>

4.3 使用測試方法進行測試

publicclass UserTest {

? ? InputStream in =null;

? ? UserMapper mapper =null;

? ? SqlSession sqlSession =null;

? ? /**? ? * 在測試方法執(zhí)行前執(zhí)行

? ? * @throws IOException

? ? */? ? @Before

? ? publicvoidinit()throws IOException {

? ? ? ? //1.讀取配置文件,生成字節(jié)流in = Resources.getResourceAsStream("SqlMapConfig.xml");

? ? ? ? //2.獲取sqlSessionFactory對象SqlSessionFactory factory =new SqlSessionFactoryBuilder().build(in);

? ? ? ? //3.獲取sqlSession對象sqlSession = factory.openSession();

? ? ? ? //4.獲取dao的代理對象mapper = sqlSession.getMapper(UserMapper.class);

? ? }

? ? /**? ? * 測試方法執(zhí)行后執(zhí)行

? ? * @throws IOException

? ? */? ? @After

? ? publicvoiddestory()throws IOException {

? ? ? ? sqlSession.commit();

? ? ? ? //6.釋放資源? ? ? ? sqlSession.close();

? ? ? ? in.close();

? ? }

? ? /**? ? * 查詢出所有用戶所對應(yīng)的賬戶

? ? */? ? @Test

? ? publicvoid findUserAndAccount(){

? ? ? ? List users = mapper.findAccountAndUser();

? ? ? ? }

}

測試結(jié)果:

  我們沒有使用Accout,也只對User進行了查詢。

Mybatis緩存

待更新。。。

源碼:https://github.com/PopsiCola/SSM-mybatis/tree/association_lazy

歡迎star

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容