当前位置: 代码网 > it编程>编程语言>Java > Mybatis延迟加载怎么配置?一对一和一对多实现方法详解

Mybatis延迟加载怎么配置?一对一和一对多实现方法详解

2026年08月19日 Java 我要评论
mybatis的延迟加载1、问题提出现一个用户有多个地址,同时一个地址对应一个用户。在查询用户信息时,要不要把关联地址查出来。在查询地址信息时,要不要把关联用户查出来。对于第一个问题,我们要确认什么时

mybatis的延迟加载

1、问题提出

现一个用户有多个地址,同时一个地址对应一个用户。

  1. 在查询用户信息时,要不要把关联地址查出来。
  2. 在查询地址信息时,要不要把关联用户查出来。
  • 对于第一个问题,我们要确认什么时候需要用户的地址信息,没有必要每次都把地址信息查询出来。因为每次查询地址信息,对我们的开销是很大的,而且每次查询都不一定需要用到地址信息。
  • 对于第二个问题,如果我们只是关心地址信息,而不知道地址信息是隶属于哪个用户,那么查出来也没有意义,所以每次查询地址信息时,都要带上用户信息。

2、延迟加载和立即加载

第一个问题就是延迟加载,第二个问题就是立即加载延迟加载:只有在使用到了对应的数据才进行查询,否则不进行查询。立即加载:不管是否使用到了,只要一调用方法,就会立马查询出来。

说明:表之间对应关系可以大致分为四种:一对一、一对多、多对一、多对多。

  • 一对多、多对多通常情况下都是使用延迟加载。
  • 一对一、多对一通常情况下都是使用立即加载。

3、实现一对一延迟加载案例演示

  • user_info表

  • address_info表

实体类

@data
public class userinfo {
    private integer id;
    private string staffid;
    private string staffname;
   /**
     * 逻辑删除
     */
    private boolean enabled;
}
@data
public class addressinfo {
    private integer addressid;
    private string userid;
    private string city;
}

输出dto对象

@data
public class addressinfodto {
    private integer addressid;
    private string userid;
    private string city;
    private userinfo userinfo;
}
@data
public class userinfodto {
    private integer id;
    private string staffid;
    private string staffname;
    private boolean enabled;
    private list<addressinfo> addressinfo;
}

实现一对一延迟加载

核心配置文件

<settings>
        <!--mybatis开启延迟加载,当开启时,所有关联对象都会延迟加载-->
        <setting name="lazyloadingenabled" value="true"/>
        <!--开启按需加载,当开启时,任何方法调用都会加载该对象的所有属性,否则,每个属性会按需加载-->
        <setting name="aggressivelazyloading" value="false"/>
  	</settings>

mapper和映射文件

public interface addressinfomapper {
	//查询所有地址信息
    list<addressinfodto> findalladdressinfo();
}

使用 association标签的select属性,指定查询地址信息的方法,后面加载地址的用户对象时,会根据配置方法路径,去调用方法执行查询用户信息。column是指定调用查询用户信息所需要的参数。

<?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.tencent.dao.mapper.addressinfomapper">
    <resultmap id="baseresultmapper" type="com.tencent.dao.entity.addressinfo">
        <id column="address_id" jdbctype="integer" property="addressid"/>
        <result column="user_id" jdbctype="varchar" property="userid"/>
        <result column="city" jdbctype="varchar" property="city"/>
    </resultmap>
    <resultmap id="addressinfodtomap" type="com.tencent.dto.addressinfodto">
        <id column="address_id" jdbctype="integer" property="addressid"/>
        <result column="user_id" jdbctype="varchar" property="userid"/>
        <result column="city" jdbctype="varchar" property="city"/>
        <association property="userinfo"  column="user_id" javatype="com.tencent.dao.entity.userinfo" select="com.tencent.dao.mapper.userinfomapper.findbystaffid">
            <id column="id" jdbctype="integer" property="id"/>
            <result column="staff_id" jdbctype="varchar" property="staffid"/>
            <result column="staff_name" jdbctype="varchar" property="staffname"/>
            <result column="enbaled" jdbctype="" property="enabled"/>
        </association>
    </resultmap>
    <!--查询所有地址信息-->
    <select id="findalladdressinfo" resultmap="addressinfodtomap">
      	select * from address_info
    </select>
</mapper>
public interface userinfomapper {
		//根据用户id查询用户信息
	    userinfo findbystaffid(@param("staffid") string staffid);
	}

添加根据用户id查询用户信息方法。

<?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">
<!--指定映射文件对应的dao实体-->
<mapper namespace="com.tencent.dao.mapper.userinfomapper">
    <resultmap id="baseresultmapper" type="com.tencent.dao.entity.userinfo">
        <id column="id" jdbctype="integer" property="id"/>
        <result column="staff_id" jdbctype="varchar" property="staffid"/>
        <result column="staff_name" jdbctype="varchar" property="staffname"/>
        <result column="enabled" jdbctype="bit" property="enabled"/>
    </resultmap>
	<!--根据用户id-->
    <select id="findbystaffid" resulttype="com.tencent.dao.entity.userinfo">
        select * from user_info where staff_id = #{staffid}
    </select>
</mapper>
<?xml version="1.0" encoding="utf-8"?>
<!doctype configuration
        public "-//mybatis.org//dtd config 3.0//en"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--mybatis的主配置文件-->
<configuration>
    <settings>
        <setting name="mapunderscoretocamelcase" value="true"/>
        <!--mybatis开启延迟加载,当开启时,所有关联对象都会延迟加载-->
        <setting name="lazyloadingenabled" value="true"/>
        <!--开启按需加载,当开启时,任何方法调用都会加载该对象的所有属性,否则,每个属性会按需加载-->
        <setting name="aggressivelazyloading" value="false"/>
    </settings>
    <!--配置数据源信息 default指的是选择数据源-->
    <environments default="mysql">
        <environment id="mysql">
            <!--配置事务类型-->
            <transactionmanager type="jdbc"></transactionmanager>
            <!--配置数据源信息-->
            <datasource type="pooled">
                <property name="driver" value="com.mysql.jdbc.driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/study-demo"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </datasource>
        </environment>
    </environments>
    <!--配置映射文件mapper文件地址-->
    <mappers>
        <mapper resource="mapper/userinfomapper.xml"/>
        <mapper resource="mapper/addressinfomapper.xml"/>
    </mappers>
</configuration>
public class testservice {
    private inputstream in = null;
    private sqlsession sqlsession = null;
    private userinfomapper userinfomapper;
    private addressinfomapper addressinfomapper;
    @before
    public void init() throws ioexception {
        //读取配置文件
        in = resources.getresourceasstream("mybatisconfig.xml");
        //创建工厂构建者
        sqlsessionfactorybuilder builder = new sqlsessionfactorybuilder();
        //构建工厂
        sqlsessionfactory factory = builder.build(in);
        //根据工厂获取session
        sqlsession = factory.opensession();
        //sqlsession构建代理对象
        userinfomapper = sqlsession.getmapper(userinfomapper.class);
        addressinfomapper = sqlsession.getmapper(addressinfomapper.class);
        system.out.println();
    }

    @after
    public void after(){
        sqlsession.commit();
        if(sqlsession != null){
            sqlsession.close();
        }
        if(in!= null){
            try {
                in.close();
            } catch (ioexception e) {
                e.printstacktrace();
            }
        }
    }

    @test
    public void test1(){
        //测试一对一延迟加载
        list<addressinfodto> alladdressinfo = addressinfomapper.findalladdressinfo();
        for (addressinfodto addressinfo : alladdressinfo) {
            system.out.println("地址信息"+addressinfo.getcity());
            system.out.println("用户地址"+addressinfo.getuserid());
        }
    }
}

执行结果

将延迟加载打开后执行结果

<settings>
        <!--mybatis开启延迟加载,当开启时,所有关联对象都会延迟加载-->
        <setting name="lazyloadingenabled" value="true"/>
        <!--开启按需加载,当开启时,任何方法调用都会加载该对象的所有属性,否则,每个属性会按需加载-->
        <setting name="aggressivelazyloading" value="true"/>
    </settings>

通过比较可以看出,当开启延迟加载,执行结果虽然相同,但是开启延迟加载后会在查看用户信息才会去数据库中进行查询,这样可以省去数据库的一下基本开销。

4、实现一对多延迟加载

实现一对多延迟加载是以查询用户信息为案例,一个用户对应多个地址信息,相关user_info的mapper文件如下

  • 使用collection 标签的select属性,指定查询用户对应地址信息的方法,当加载用户地址信息时,会根据column属性所配置的参数,执行查询用户地址信息方法。
<?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.tencent.dao.mapper.userinfomapper">
    <resultmap id="baseresultmapper" type="com.tencent.dao.entity.userinfo">
        <id column="id" jdbctype="integer" property="id"/>
        <result column="staff_id" jdbctype="varchar" property="staffid"/>
        <result column="staff_name" jdbctype="varchar" property="staffname"/>
        <result column="enabled" jdbctype="bit" property="enabled"/>
    </resultmap>
    <resultmap id="userinfodtomap" type="com.tencent.dto.userinfodto">
        <id column="id" jdbctype="integer" property="id"/>
        <result column="staff_id" jdbctype="varchar" property="staffid"/>
        <result column="staff_name" jdbctype="varchar" property="staffname"/>
        <result column="enabled" jdbctype="bit" property="enabled"/>
        <collection property="addressinfo" column="staff_id" select="com.tencent.dao.mapper.addressinfomapper.findbyuserid" oftype="com.tencent.dao.entity.addressinfo"/>
    </resultmap>
    <select id="findalluserinfo" resultmap="userinfodtomap">
        select * from user_info
    </select>
</mapper>

地址信息对应的映射mapper文件

  • 提供一个根据用户id查询所有的地址信息方法
<?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.tencent.dao.mapper.addressinfomapper">
    <resultmap id="baseresultmapper" type="com.tencent.dao.entity.addressinfo">
        <id column="address_id" jdbctype="integer" property="addressid"/>
        <result column="user_id" jdbctype="varchar" property="userid"/>
        <result column="city" jdbctype="varchar" property="city"/>
    </resultmap>
    <select id="findbyuserid" resulttype="com.tencent.dao.entity.addressinfo">
          select * from address_info where user_id = #{userid}
    </select>
</mapper>

测试开启延迟加载执行结果

 <settings>
        <!--mybatis开启延迟加载,当开启时,所有关联对象都会延迟加载-->
        <setting name="lazyloadingenabled" value="true"/>
        <!--开启按需加载,当开启时,任何方法调用都会加载该对象的所有属性,否则,每个属性会按需加载-->
        <setting name="aggressivelazyloading" value="true"/>
 </settings>

可以看出,先执行了查询所有用户信息的sql语句,然后再挨个查询每个用户下的地址信息,实现了延迟加载。

总结

mybatis的延迟加载是通过 lazyloadingenabledaggressivelazyloading 属性进行控制的,当一对一需要实现延迟加载时,需要打开延迟加载开关以及通过<association>标签的select 属性指定延迟加载对象查询的方法路径,column属性指定执行参数,在使用到其延迟加载对象时,mybatis才会进行查询。

当一对多时,通过<collection>标签的select属性指定延迟加载对象查询的方法路径,column属性指定执行参数,在使用到其延迟加载对象时,mybatis才会进行查询。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com