深入解析:MyBatis框架 - 延迟加载+一/二级缓存

news/2026/1/25 15:11:33/文章来源:https://www.cnblogs.com/gccbuaa/p/19529760

目录

  • 一、延迟加载
    • 立即加载
    • 延迟加载
    • 实操案例
  • 二、缓存
    • 一级缓存
    • 二级缓存

一、延迟加载

立即加载

概念: 当查询主对象时,立即执行所关联的sql语句,一次性将对象数据全部查询出来。
行为: 执行SELECT * FROM order WHERE id = #{id}后,立马执行SELECT * FROM user WHERE id = #{userId}
使用场景: 多对一查询
优点: 数据一次性加载完毕,响应速度快。
缺点: 可能查询出不需要的数据,造成数据库资源和网络传输的浪费,降低性能。
使用: 默认使用立即加载。

延迟加载

概念: 当查询主对象时,只查询主对象的数据。关联对象的数据不会立即查询,只用程序第一次真正访问关联对象时,才会加载关联对象的数据。
行为: 先执行SELECT * FROM order WHERE id = #{id},当调用order.getUser()方法时,才执行SELECT * FROM user WHERE id = #{userId}

使用场景: 一对多查询
优点: 按需加载,避免了不必要的数据库查询。
缺点: 当第一次访问关联对象时,会有个短暂的查询延迟。后续访问多个关联对象,会产生多次数据库查询。
使用: 需要手动开启延迟加载。

  • 在主配置文件中开启延迟加载:lazyLoadingEnabledtrue开启延迟加载,aggressiveLazyLoading控制延迟加载的行为,默认值为false,按需加载
  • 在子配置文件中:在<association>标签或<collection>标签中设置fetchType指定哪个关联查询使用延迟加载。
    • fetchType属性值:lazy - 延迟加载;eager - 立即加载

实操案例

将一对多查询和多对一查询都进行延迟加载演示:
多对一延迟加载实操案例演示:

  • 在AccountMapper接口类中编写方法
    package com.tx.mapper;
    import com.tx.entity.Account;
    import java.util.List;
    public interface AccountMapper {
    // 延迟加载:多对一查询,查询某一个用户的所有账户信息
    public List<Account> findAccountAll();}
  • 在AccountMapper.xml中进行配置和SQL语句
    <mapper namespace="com.tx.mapper.AccountMapper"><!--延迟加载:多对一查询--><!--内连接查询--><select id="findAccountAll" resultMap="accountMap">select * from account</select><!--通过用户的id查询账户信息--><select id="findByUid" parameterType="int" resultType="account">select * from account where uid = #{uid}</select><!--配置映射--><resultMap id="accountMap" type="account"><result property="id" column="id" /><result property="uid" column="uid" /><result property="money" column="money" /><!--在多的一方指定关联查询的延迟加载--><association property="user" javaType="user"select="com.tx.mapper.UserMapper.findUserById" column="uid" fetchType="lazy"><id property="id" column="id"/><result property="username" column="username" /><result property="birthday" column="birthday"/><result property="sex" column="sex"/><result property="address" column="address" /></association></resultMap></mapper>
  • 在UserMapper接口类中编写方法
    package com.tx.mapper;
    import com.tx.entity.User;
    import java.util.List;
    public interface UserMapper {
    // 延迟加载:多对一查询
    public List<User> findUserById(Integer uid);}
  • 在UserMapper.xml中进行配置文件
    <mapper namespace="com.tx.mapper.UserMapper"><!--配置延迟加载:多对一查询--><select id="findUserById" parameterType="int" resultType="user">select * from user where id = #{id}</select></mapper>
  • 在主配置文件中开启延迟加载
    <configuration><!--配置延迟加载--><settings><!-- 开启延迟加载 --><setting name="lazyLoadingEnabled" value="true"/><!-- 将积极加载改为消极加载及按需加载 --><setting name="aggressiveLazyLoading" value="false"/></settings><!--定义类型别名--><typeAliases><package name="com.tx.entity" /></typeAliases><!--主配置文件--><!--配置环境们--><environments default="mysql"><!--配置环境--><environment id="mysql"><!--配置事务的类型,使用本地事务策略--><transactionManager type="JDBC"></transactionManager><!--配置是否使用连接池 POOLED表示使用链接池,UNPOOLED表示不使用连接池--><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql:///mybatis_db"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><!--加载映射文件--><mappers><mapper resource="mapper/UserMapper.xml"></mapper><mapper resource="mapper/AccountMapper.xml"></mapper></mappers></configuration>
  • 测试代码
    package com.tx.test;
    import com.tx.entity.Account;
    import com.tx.entity.User;
    import com.tx.mapper.AccountMapper;
    import com.tx.mapper.UserMapper1;
    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 Test01 {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    @Before
    public void init() throws IOException {
    // 1. 加载主配置文件,目的是构建SqlSessionFactory对象
    in = Resources.getResourceAsStream("SqlMapConfig.xml");
    // 2. 创建SqlSessionFactory(Sql会话工厂)对象
    factory = new SqlSessionFactoryBuilder().build(in);
    // 3. 获取session对象,使用SqlSessionFactory工厂对象创建SqlSession对象
    session = factory.openSession();
    }
    @After
    public void destory() throws IOException {
    // 5. 释放资源
    session.close();
    in.close();
    }
    // 4.1 延迟加载:多对一查询
    @Test
    public void testFindAccountAll(){
    // 4.1.1 通过session创建Mapper接口的代理对象
    AccountMapper mapper = session.getMapper(AccountMapper.class);
    // 4.1.2 执行方法
    List<Account> list = mapper.findAccountAll();for (Account account:list){System.out.println("开始……");System.out.println(account.getMoney());System.out.println(account.getUser().getUsername());System.out.println("结束……");System.out.println();}}}

结果
一对多延迟加载实操案例演示:

  • 在UserMapper接口类中编写方法
    package com.tx.mapper;
    import com.tx.entity.User;
    import java.util.List;
    public interface UserMapper1 {
    // 延迟加载:一对多查询
    public List<User> findUserAll();}
  • 在UserMapper.xml中进行配置和SQL语句
    <mapper namespace="com.tx.mapper.UserMapper1"><!--配置延迟加载:一对多查询--><select id="findUserAll" resultMap="userMap">select * from user</select><!--数据封装--><resultMap id="userMap" type="user"><id property="id" column=""/><result property="username" column="username"/><result property="birthday" column="birthday"/><result property="sex" column="sex"/><result property="address" column="address"/><!--select="":使用账号的方法查询column="":使用id值去查询账号--><collection property="accounts" ofType="account"select="com.tx.mapper.AccountMapper1.findAccountByUid" column="id" fetchType="lazy"><id property="id" column="id"/><result property="uid" column="uid"/><result property="money" column="money"/></collection></resultMap></mapper>
  • 在AccountMapper接口类中编写方法
    package com.tx.mapper;
    import com.tx.entity.Account;
    import java.util.List;
    public interface AccountMapper1 {
    // 延迟加载:一对多查询
    public List<Account> findAccountByUid(Integer uid);}
  • 在AccountMapper.xml中进行配置和SQL语句
    <mapper namespace="com.tx.mapper.AccountMapper1"><!--延迟加载:一对多查询--><!--通过用户的id查询账户信息--><select id="findAccountByUid" parameterType="int" resultType="account">select * from account where uid = #{uid}</select></mapper>
  • 在主配置文件中开启延迟加载
    <configuration><!--配置延迟加载--><settings><!-- 开启延迟加载 --><setting name="lazyLoadingEnabled" value="true"/><!-- 将积极加载改为消极加载及按需加载 --><setting name="aggressiveLazyLoading" value="false"/></settings><!--定义类型别名--><typeAliases><package name="com.tx.entity" /></typeAliases><!--主配置文件--><!--配置环境们--><environments default="mysql"><!--配置环境--><environment id="mysql"><!--配置事务的类型,使用本地事务策略--><transactionManager type="JDBC"></transactionManager><!--配置是否使用连接池 POOLED表示使用链接池,UNPOOLED表示不使用连接池--><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql:///mybatis_db"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><!--加载映射文件--><mappers><mapper resource="mapper/UserMapper1.xml"></mapper><mapper resource="mapper/AccountMapper1.xml"></mapper><mapper resource="mapper/UserMapper2.xml"></mapper></mappers></configuration>
  • 测试代码
    // 4.2 延迟加载:一对多查询
    @Test
    public void testFindUserAll(){
    // 4.2.1 通过session创建Mapper接口的代理对象
    UserMapper1 mapper = session.getMapper(UserMapper1.class);
    // 4.2.2 执行方法
    List<User> list = mapper.findUserAll();for (User user:list){System.out.println("开始……");System.out.println(user.getUsername());System.out.println(user.getAccounts());System.out.println("结束……");System.out.println();}}

一级缓存

二、缓存

MySQL使用sql语句缓存。例如,select * from user和select *         from user,看起来时同一个表,但是,在MySQL缓存中,用第二表查询不到User表中的数据
MyBtais将数据进行缓存。

一级缓存

级别: SqlSession级别

实操案例:

  1. 在UserMapper2接口类中编写方法
    package com.tx.mapper;
    import com.tx.entity.User;
    public interface UserMapper2 {
    // 一/二级缓存
    public User findById(Integer id);
    }
  2. 在UserMapper2.xml中配置Sql语句
    <select id="findById" parameterType="int" resultType="user">select * from user where id = #{id}
    </select>
  3. 测试代码
    package com.tx.test;
    import com.tx.entity.User;
    import com.tx.mapper.UserMapper2;
    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;
    public class Test02 {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    @Before
    public void init() throws IOException {
    // 1. 加载主配置文件,目的是构建SqlSessionFactory对象
    in = Resources.getResourceAsStream("SqlMapConfig.xml");
    // 2. 创建SqlSessionFactory(Sql会话工厂)对象
    factory = new SqlSessionFactoryBuilder().build(in);
    // 3. 获取session对象,使用SqlSessionFactory工厂对象创建SqlSession对象
    session = factory.openSession();
    }
    @After
    public void destory() throws IOException {
    // 5. 释放资源
    session.close();
    in.close();
    }
    // 4.1 一级缓存:会话级别
    @Test
    public void testFindById(){
    // 获取代理对象
    UserMapper2 mapper = session.getMapper(UserMapper2.class);
    // 调用方法,通过主键查询
    // 先查询一级缓存,没有数据。
    // 会查数据库,都会有sql语句,把查询出来的数据存储到一级缓存中
    User user = mapper.findById(1);
    System.out.println(user);
    System.out.println("==================================");
    // 清除缓存
    // session.clearCache();
    // 在查询一次
    // 先查询一级缓存,存在数据。
    // 从缓存中把数据返回,就没有sql语句
    User user1 = mapper.findById(1);
    // 这两个user对象地址一样
    System.out.println(user1);
    }
    }

二级缓存

级别: SqlSessionFactory级别
需要手动开启二级缓存:

  • 在主配置文件开启二级缓存
    <!--配置延迟加载--><settings><!-- 开启延迟加载 --><setting name="lazyLoadingEnabled" value="true"/><!-- 将积极加载改为消极加载及按需加载 --><setting name="aggressiveLazyLoading" value="false"/><!--开启二级缓存--><setting name="cacheEnabled" value="true"/></settings>
  • 在子配置文件开启二级缓存
    <!--开启二级缓存--><cache/>

除此之外,还有一个重要的条件:

  • 实体类一定要继承Serializable对象流

实操案例:

  • 测试代码
// 4.2 二级缓存:会话工厂级别
// 二级缓存的使用对象地址不同,但是也是从缓存加载。原因是二级缓存存储的是零散数据,组装出来的对象
@Test
public void testFindById2(){
// 获取代理对象
UserMapper2 mapper = session.getMapper(UserMapper2.class);
// 调用方法,通过主键查询
// 先查询一级缓存,没有数据。
// 会查数据库,都会有sql语句,把查询出来的数据存储到一级缓存中
User user = mapper.findById(1);
System.out.println(user);
System.out.println("==================================");
// 关闭会话
session.close();
// 获取session对象 和 获取代理对象
session = factory.openSession();
UserMapper2 mapper1 = session.getMapper(UserMapper2.class);
// 在查询一次
// 先查询一级缓存,存在数据。
// 从缓存中把数据返回,就没有sql语句
User user1 = mapper1.findById(1);
// 这两个user对象地址一样
System.out.println(user1);
}

二级缓存

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1214885.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深聊氨基酸洗发产品,好用的品牌都在这了

在个护市场竞争白热化的当下,一款真正的氨基酸洗发产品是品牌在洗护赛道立足的硬通货,关乎消费者信任与市场份额。面对众多标榜氨基酸的产品,如何筛选有实力的氨基酸洗发产品企业?以下依据不同合作模式,为你推荐2…

导师推荐2026最新!9款AI论文工具测评:专科生毕业论文必备

导师推荐2026最新&#xff01;9款AI论文工具测评&#xff1a;专科生毕业论文必备 2026年AI论文工具测评&#xff1a;为何值得一看&#xff1f; 随着人工智能技术的不断进步&#xff0c;AI论文工具已成为专科生毕业论文写作过程中不可或缺的辅助工具。然而&#xff0c;面对市场上…

Java毕设选题推荐:基于 SpringBoot 的网上鲜花销售花店管理系统的设计与实现 基于springboot的鲜花销售管理系统的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

Java毕设选题推荐:基于springboot的社区独居老人健康管理系统社区空巢老人健康管理系统 【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

BERT微调加速

&#x1f493; 博客主页&#xff1a;借口的CSDN主页 ⏩ 文章专栏&#xff1a;《热点资讯》 BERT微调加速&#xff1a;边缘计算驱动的范式革新与未来路径目录BERT微调加速&#xff1a;边缘计算驱动的范式革新与未来路径 引言&#xff1a;微调瓶颈与加速的迫切性 维度一&#xff…

2005-2024年上市公司管理者短视主义数据+stata代码

数据名称&#xff1a;2005-2024年管理者短视主义数据 时间&#xff1a;2005-2024年 数据量&#xff1a;53104条 范围&#xff1a;沪深A股上市公司 包含剔除金融stpt、未剔除版本 包含原始数据、处理代码&#xff08;stata&#xff09;、最终结果 指标构建&#xff1a;基于…

2007-2024年上市公司媒体关注日、年数据

数据简介 报刊媒体关注度&#xff1a;指传统纸质媒体&#xff08;如报纸、杂志&#xff09;对特定议题、事件、人物、组织或产品等进行报道、讨论和传播的程度与强度。它反映了传统媒体在舆论场中的聚焦程度&#xff0c;是评估社会影响力和公众认知度的关键维度之一。 网络媒…

2010-2024年地级市新质生产力数据

地级市新质生产力数据 2010-2024年 战略性新兴产业产值 战略性新兴产业员工人数 数据说明&#xff1a; 1.战略性新兴产业和新一代信息技术产业的度量方式 参考文献&#xff1a; [1]王珏,秦文晋.中国战略性新兴产业绿色全要素生产率增长的要素源泉及动态演化[J].产业经济评论…

详细介绍:【C++入门必备】 最详细安装入门教程(一)

详细介绍:【C++入门必备】 最详细安装&入门教程(一)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consol…

总结国内认证权威的芳疗师培训学校,爱芙悦芳疗学院实力强劲

2026年健康产业与生活美学市场持续升温,芳疗师作为融合自然疗愈与专业技能的新兴职业,成为众多追求身心平衡者的职业选择。然而,国内芳疗师培训市场乱象频发:准入门槛低导致教学质量参差不齐,认证体系混乱让初学者…

2025年热转印机选购必看:高口碑实力厂商全解析,服务好的热转印机品牌精选综合实力TOP企业

随着个性化消费与短单快反生产模式的兴起,热转印技术凭借其操作便捷、图案精细、适用材质广泛等优势,在塑胶、包装、礼品、电子电器等众多行业中的应用持续深化。然而,面对市场上品牌林立、功能各异的热转印设备,采…

Java毕设项目推荐-基于springboot+vue的鲜花盆栽绿植销售系统设计与实现基于springboot的鲜花销售管理系统的设计与实现【附源码+文档,调试定制服务】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

2025年度上海防疫物资回收企业推荐:环保贡献突出,隔离衣回收/防护服回收/防疫物资回收,防疫物资回收机构排行榜单

随着公共卫生体系对防疫物资管理的精细化要求提升,医疗物资回收行业正从“粗放处置”向“合规化、资源化”转型。据统计,2024年全国医疗防疫物资回收市场规模突破320亿元,其中上海作为国际化大都市,医疗资源密集,…

盘点苏州电动升降机生产厂技术强的有哪些,推荐靠谱厂家

随着工业自动化进程加速,企业对高效、安全的物料搬运设备需求日益增长,电动升降机作为物流与生产环节的核心工具,其生产厂家的技术实力、定制能力与服务可靠性成为企业选型的关键。本文围绕电动升降机生产厂哪家技术…

年升降平台哪个制造商质量过硬,这几家值得关注

2026年制造业与物流行业智能化升级加速,高效、安全的升降平台已成为企业优化仓储流转、提升生产效率的核心设备。无论是重型货物的垂直搬运、车间生产线的高度适配,还是冷链仓储的特殊环境作业,升降平台的质量稳定性…

升降平台制造厂哪家合作案例多,无锡靠谱厂家推荐

2026年工业物流智能化浪潮下,升降平台作为衔接生产、仓储、物流全链路的核心设备,其制造企业的合作案例丰富度、成本控制能力与研发技术实力,直接决定企业物流效率提升与长期运营稳定性。无论是汽车制造车间的重型物…

[Tools] Using Cloudflared to expose your local server to public

For example, when you use Dify to create a workflow and need to send a HTTP request to your local request for testing... Due to the request is send from Dify server, which not able to access your local…

留香持久沐浴露推荐,恋香花语性价比高的产品怎么选?

问题1:什么样的沐浴露才算天然成分沐浴露?选择时要避开哪些坑? 在消费升级的背景下,天然成分沐浴露成为越来越多家庭的选择,但很多用户对天然的认知仍停留在植物标签层面,容易陷入误区。首先要明确:真正的天然成…

Java毕设项目:基于springboot的鲜花销售管理系统的设计与实现(源码+文档,讲解、调试运行,定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…