Mybatis的延迟加载

Mybatis的延迟加载

 一、什么是延迟加载

延迟加载:  就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。延迟加载也称懒加载.好处:  先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速度要快。坏处:  因为只有当需要用到数据时,才会进行数据库查询,这样在大批量数据查询时,因为查询工作也要消耗时间,所以可能造成用户等待时间变长,造成用户体验下降。

二、实现需求

需求:  查询账户(Account)信息并且关联查询用户(User)信息。如果先查询账户(Account)信息即可满足要求,当我们需要查询用户(User)信息时再查询用户(User)信息。把对用户(User)信息的按需去查询就是延迟加载。  association、collection 具备延迟加载功能。

三、使用association实现延迟加载  

需求:

查询账户信息同时查询用户信息。

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 {


    /**    * 查询账户所对应的的用户

    */    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>

        <!--一对一的关系映射 JavaType:对应的是哪个类 select 指定的内容:查询用户的唯一标识 -->

        <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 {


    /**    * 根据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">   

    <!--配置 查询结果的列名和实体类的属性名的对应关系-->   

    <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>    <!--查询出用户所对应的账户-->   

<select id="findAccountAndUser" resultMap="userMap">        select * from user left outer join account on user.id = account.uid    </select>    <!--根据id查询用户-->    <select id="findById" resultType="user" parameterType="int">        select * from user where id = #{id}    </select></mapper>


3.5 开启mybatis的延迟加载策略

进入 Mybaits 的官方文档,找到 settings 的说明信息:


我们需要在 Mybatis 的配置文件 SqlMapConfig.xml 文件中添加延迟加载的配置。

    <!--配置参数,延迟加载-->

    <settings>

        <!--开启mybatis支持延迟加载-->

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

        <!--不配置也可以:默认为false;允许触发方法进行延迟加载,否则立即加载-->

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

    </settings>

3.6 编写测试只查账户信息不查用户信息

*/publicclass AccountTest {

    InputStream in =null;

    AccountMapper mapper =null;

    SqlSession sqlSession =null;

    /**    * 在测试方法执行前执行

    * @throws IOException

    */    @Before

    publicvoidinit()throws IOException {

        //1.读取配置文件,生成字节流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);

    }

    /**    * 测试方法执行后执行

    * @throws IOException

    */    @After

    publicvoiddestory()throws IOException {

        sqlSession.commit();

        //6.释放资源        sqlSession.close();

        in.close();

    }

    /**    * 查询出账户所对应的user

    */    @Test

    publicvoid testFindAccountAndUser(){

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

}


3.7 测试结果

当不进行配置时,立即加载,查询account所对应的user,一起将user查询出来:

  配置后,对account进行查询放入到list集合中,并没有涉及到user对象,所以就没有发出 SQL 语句查询账户所关联的 User 对象的查询。:

四、使用collection实现缓存策略

同样我们也可以在一对多关系配置的<collection>结点中配置延迟加载策略。

<collection>结点中也有 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;

    //一对多关系。一的方包含多的一方所有对象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 {

    /**    * 根据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">

<!--配置 查询结果的列名和实体类的属性名的对应关系-->

<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> <!--查询出用户所对应的账户-->

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

        select * from user

    </select>

    <!--根据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;

    /**    * 在测试方法执行前执行

    * @throws IOException

    */    @Before

    publicvoidinit()throws IOException {

        //1.读取配置文件,生成字节流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);

    }

    /**    * 测试方法执行后执行

    * @throws IOException

    */    @After

    publicvoiddestory()throws IOException {

        sqlSession.commit();

        //6.释放资源        sqlSession.close();

        in.close();

    }

    /**    * 查询出所有用户所对应的账户

    */    @Test

    publicvoid findUserAndAccount(){

        List users = mapper.findAccountAndUser();

        }

}

测试结果:

  我们没有使用Accout,也只对User进行了查询。

Mybatis缓存

待更新。。。

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

欢迎star

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容