关于MyBatis的一些面试题

mybatis的执行流程

MyBatis 的执行流程主要包括 SQL 解析、参数绑定、执行查询/更新、结果映射等几个步骤。下面详细解释每个步骤的执行流程:

1. 加载配置文件和映射文件

  • 加载 MyBatis 配置文件:启动时,MyBatis 通过 SqlSessionFactoryBuilder 读取并解析核心配置文件(mybatis-config.xml)和映射文件(*.xml)。
  • 创建 SqlSessionFactory:通过解析配置文件,MyBatis 会构建 SqlSessionFactory 对象,该对象负责生成 SqlSession

2. 创建 SqlSession

  • 创建 SqlSession:通过 SqlSessionFactory 获取 SqlSession 对象。SqlSession 是 MyBatis 的核心接口之一,负责执行 SQL 语句、获取映射器、提交事务等。
  • 绑定 Mapper 接口SqlSession 会根据开发者定义的接口,创建与之对应的 Mapper 动态代理对象,负责处理 SQL 操作。

3. 执行 SQL 语句

  • 调用 Mapper 接口方法:当调用 Mapper 接口的方法时,MyBatis 会找到与接口方法对应的 SQL 语句(Mapper XML 文件或注解方式定义的 SQL)。
  • 动态生成 SQL 语句:根据方法传递的参数,MyBatis 会动态生成 SQL 语句(包括 #{} 或 ${} 占位符的替换)。
    • #{} 占位符:采用预编译方式,防止 SQL 注入。
    • ${} 占位符:直接替换为字符串,不会进行预编译。

4. 参数处理

  • ParameterHandler 参数处理器:MyBatis 内部使用 ParameterHandler 将传递的参数与 SQL 中的占位符进行绑定,并处理各种参数类型(如基本类型、JavaBean、Map、List等)。

5. SQL 执行

  • Executor 执行器:MyBatis 中的执行器(SimpleExecutorReuseExecutorBatchExecutor 等)负责执行 SQL 语句。执行器负责与数据库进行交互,并处理缓存等事务。
  • 二级缓存:在执行 SQL 之前,MyBatis 会先检查二级缓存,如果缓存中有结果,则直接返回缓存数据;否则继续查询数据库。

6. 映射结果

  • ResultSetHandler 结果集处理器:SQL 查询结果返回后,ResultSetHandler 会将查询结果集映射到 Java 对象。它会根据配置的映射规则(如 XML 文件中的 resultMap,或通过注解的方式)将结果映射成对象。
  • 类型转换:MyBatis 支持多种数据类型的转换,如将数据库中的字段映射为 JavaBean 中的属性。

7. 事务管理

  • 手动提交和自动提交:默认情况下,MyBatis 会自动提交事务;如果配置为手动提交,则需要调用 commit() 方法来提交事务。
  • 事务控制:MyBatis 通过 Transaction 接口管理事务,包括事务的提交、回滚等操作。

8. 关闭 SqlSession

  • 资源释放:在执行完操作后,必须关闭 SqlSession,以释放数据库连接资源。SqlSession 的生命周期由开发者管理,建议使用 try-finally 结构来确保关闭。

MyBatis 执行流程图(可视化)

graph TD;
  A[加载MyBatis配置文件] --> B[创建SqlSessionFactory];
  B --> C[获取SqlSession];
  C --> D[调用Mapper接口方法];
  D --> E[动态生成SQL];
  E --> F[参数绑定];
  F --> G[执行SQL];
  G --> H[检查二级缓存];
  H --> I[查询数据库];
  I --> J[映射查询结果];
  J --> K[返回结果到调用者];
  C --> L[提交或回滚事务];
  K --> M[关闭SqlSession];

总结

  • 核心对象SqlSessionFactorySqlSessionExecutor
  • 核心操作:参数绑定、执行 SQL、结果映射、事务管理。

MyBatis延迟加载使用以及原理

MyBatis 的延迟加载(Lazy Loading)是指当需要用到某些数据时,才执行对应的 SQL 语句去查询数据库。这种机制可以有效减少不必要的数据库查询,提高系统性能。

1. MyBatis 延迟加载的使用

延迟加载的应用场景通常出现在一对一一对多关系的查询中。例如,查询订单时,每个订单可能会包含多个商品,但你可能只想在需要查看商品时才加载它们,而不是每次查询订单都加载所有商品数据。

配置方式

在 MyBatis 的核心配置文件 mybatis-config.xml 中,可以通过以下配置来启用延迟加载功能:

<configuration>
    <settings>
        <!-- 开启延迟加载 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 代理所有属性,延迟加载时一次性加载所有 -->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
</configuration>
  • lazyLoadingEnabled:启用延迟加载。
  • aggressiveLazyLoading:如果设置为 false,则只会在访问某个懒加载属性时才加载该属性的数据;如果设置为 true,一旦访问一个延迟加载的属性,所有延迟加载的属性都会被加载。

示例:一对多关系(订单和商品)

假设你有一个 OrderProduct 的一对多关系,Order 中包含一个 List<Product>

SQL Mapper 映射:

<resultMap id="orderMap" type="com.example.Order">
    <id column="order_id" property="id"/>
    <result column="order_name" property="name"/>
    <!-- 多对一映射(延迟加载) -->
    <collection property="products" ofType="com.example.Product"
                select="selectProductsByOrderId" lazy="true"/>
</resultMap>

<!-- 查询订单 -->
<select id="selectOrderById" resultMap="orderMap">
    SELECT * FROM orders WHERE order_id = #{id}
</select>

<!-- 查询订单的商品(延迟加载部分) -->
<select id="selectProductsByOrderId" resultType="com.example.Product">
    SELECT * FROM products WHERE order_id = #{id}
</select>

Java 类:

public class Order {
    private Integer id;
    private String name;
    // 一对多关系,商品列表
    private List<Product> products;
    // getter and setter
}

public class Product {
    private Integer id;
    private String productName;
    private Double price;
    // getter and setter
}

2. MyBatis 延迟加载的原理

MyBatis 延迟加载的实现依赖于Java 的动态代理机制。在加载 Order 对象时,MyBatis 不会立刻查询 products 数据,而是为 products 属性创建一个代理对象(Proxy),这个代理对象会记录当前对象的状态和代理方法的调用。

延迟加载的步骤:
  1. 第一次查询: 当调用 selectOrderById 查询 Order 时,MyBatis 只会执行订单表的查询,将 products 属性用代理对象代替,但不会立即查询 products 表中的数据。

  2. 访问延迟加载属性: 当你调用 order.getProducts() 时,MyBatis 会通过代理对象检测到该属性被调用,从而触发第二次查询,执行 selectProductsByOrderId 语句查询商品数据。

  3. 加载数据: 查询结果被返回并填充到 products 列表中。

工作原理
  • MyBatis 通过使用 CGLIBJDK 动态代理,为延迟加载的属性生成代理对象。当延迟加载的属性被调用时,代理对象会执行一个回调,动态加载所需的数据。
  • 代理模式 是延迟加载的核心。Proxy 对象会在调用目标属性时检查属性的加载状态,未加载时会触发查询并加载数据。
延迟加载控制的要点
  • 延迟加载需要在事务中使用,因为需要在对象的生命周期内保持数据库会话的连接状态。
  • 只有在属性被真正调用时,才会触发延迟加载。
注意事项
  • 如果你在 MyBatis 配置文件中将 aggressiveLazyLoading 设置为 true,一旦加载了某个延迟属性,所有延迟属性都会加载。这个配置适合当你需要尽快获取所有关联对象时。

3. 延迟加载和立即加载的对比

  • 延迟加载:只有在需要用到相关数据时,才会查询数据库并加载,适合处理关系型数据或减少不必要的查询。
  • 立即加载:一次性查询出所有关联数据,适合那些频繁需要访问的关联对象,避免后续多次查询数据库。

4. 总结

  • 延迟加载在查询一对多、多对一时非常有用,可以避免不必要的数据库查询。
  • MyBatis 通过动态代理机制实现延迟加载,当你访问某个延迟加载的属性时,才会触发相应的 SQL 查询。
  • 通过 lazyLoadingEnabledaggressiveLazyLoading 配置项,可以控制 MyBatis 延迟加载的行为。

MyBatis一级二级缓存

在 MyBatis 中,缓存是为了减少数据库查询的次数,提升性能。MyBatis 提供了两级缓存机制:一级缓存二级缓存

1. 一级缓存

一级缓存是SqlSession 级别的缓存,它的作用范围仅限于同一个 SqlSession 对象。在同一个 SqlSession 中,多次查询同一个数据时,MyBatis 会将查询结果存储到缓存中,之后的相同查询就可以直接从缓存中获取结果,而不再执行 SQL 查询。

一级缓存的特点
  • 默认开启:不需要配置,它会自动在 SqlSession 中工作。
  • 作用范围:仅限于同一个 SqlSession,当 SqlSession 关闭后,一级缓存也会被清除。
  • 缓存机制:以 statement ID(SQL 语句的唯一标识)查询参数 作为缓存的 key,查询结果作为 value。
  • 失效条件
    • 如果执行了 INSERTUPDATEDELETE 操作,一级缓存会被清空,因为数据发生了变化。
    • 手动清除缓存,例如调用 sqlSession.clearCache() 方法。
    • SqlSession 关闭时,一级缓存也会失效。

一级缓存的示例

SqlSession sqlSession = sqlSessionFactory.openSession();
// 第一次查询
User user1 = sqlSession.selectOne("com.example.mapper.UserMapper.selectUser", 1);
System.out.println(user1); // 查询数据库并缓存结果

// 第二次查询相同数据
User user2 = sqlSession.selectOne("com.example.mapper.UserMapper.selectUser", 1);
System.out.println(user2); // 从缓存中获取结果,不查询数据库

2. 二级缓存

二级缓存是Mapper 级别的缓存,它的作用范围是同一个 Mapper 映射文件,即相同的 Mapper 共享二级缓存。二级缓存是一个跨 SqlSession 的缓存,它允许不同的 SqlSession 共享缓存,提高数据查询的效率。

二级缓存的特点
  • 需要手动开启:二级缓存默认是关闭的,必须在 MyBatis 的配置文件或 Mapper 映射文件中进行配置才能使用。
  • 作用范围:整个 Mapper 级别,不同的 SqlSession 可以共享相同的缓存数据。
  • 缓存机制:与一级缓存类似,使用 statement ID查询参数 作为 key,查询结果作为 value 存入缓存中。
  • 失效条件
    • 执行 INSERTUPDATEDELETE 操作时,二级缓存会失效。
    • 手动清除缓存或配置的缓存清理策略。
    • 配置了缓存的过期时间,超时后缓存失效。
开启二级缓存的步骤
  1. 在核心配置文件中启用二级缓存

<configuration>c
    <settings>
        <!-- 启用全局二级缓存 -->
        <setting name="cacheEnabled" value="true"/>
    </settings>
</configuration>

   2. 在 Mapper 映射文件中启用二级缓存: 在对应的 Mapper.xml 文件中,添加如下配置:

<cache/>

  3.使用 Serializable 接口: 由于二级缓存中的对象是以序列化的形式存储的,所有被缓存的对象必须实现 Serializable 接口。

二级缓存的示例
  1. Mapper 映射文件中启用二级缓存

<mapper namespace="com.example.mapper.UserMapper">
    <cache/>
    <select id="selectUser" parameterType="int" resultType="com.example.User">
        SELECT * FROM user WHERE id = #{id}
    </select>
</mapper>

Java 代码示例

SqlSession sqlSession1 = sqlSessionFactory.openSession();
User user1 = sqlSession1.selectOne("com.example.mapper.UserMapper.selectUser", 1);
sqlSession1.close(); // 查询结果存入二级缓存

SqlSession sqlSession2 = sqlSessionFactory.openSession();
User user2 = sqlSession2.selectOne("com.example.mapper.UserMapper.selectUser", 1);
sqlSession2.close(); // 直接从二级缓存中获取结果,不再查询数据库

3. 一级缓存与二级缓存的区别

4. 二级缓存的实现原理

二级缓存是基于持久化的缓存机制实现的,缓存数据可以存储到磁盘或内存中。MyBatis 通过 Cache 接口提供二级缓存的基本操作,开发者可以自定义缓存实现。常见的实现有:

  • PerpetualCache:MyBatis 默认的缓存实现,使用 HashMap 存储数据。
  • LRU (Least Recently Used):最近最少使用算法。
  • FIFO (First In First Out):先进先出算法。
  • Soft Cache:基于 Java 的软引用,缓存会在内存不足时自动清除。
  • Weak Cache:基于 Java 的弱引用,缓存会在下一次 GC 时自动清除。

5. 总结

  • 一级缓存 是 MyBatis 默认开启的 SqlSession 级别的缓存,在同一个 SqlSession 中重复查询相同数据时,使用缓存。
  • 二级缓存Mapper 级别的缓存,需要手动配置,可以在不同的 SqlSession 中共享查询结果。
  • 二级缓存需要开发者确保数据的一致性,因为二级缓存跨 SqlSession 共享,可能导致旧数据在缓存中被使用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Transformer图解以及相关的概念

前言 transformer是目前NLP甚至是整个深度学习领域不能不提到的框架&#xff0c;同时大部分LLM也是使用其进行训练生成模型&#xff0c;所以transformer几乎是目前每一个机器人开发者或者人工智能开发者不能越过的一个框架。接下来本文将从顶层往下去一步步掀开transformer的面…

2018年计算机网络408真题解析

第一题&#xff1a; 解析&#xff1a;TCP/IP体系结构应用层常用协议及其相应的运输层协议 TCP协议是面向连接可靠数据传输服务&#xff0c;UDP无连接不可靠的数据传输服务&#xff0c;IP无连接不可靠的数据连接服务。 FTP协议&#xff0c;SMTP协议和HTTP协议使用TCP协议提供的面…

SaaS架构:中央库存系统架构设计

大家好&#xff0c;我是汤师爷~ 近年来&#xff0c;越来越多的零售企业大力发展全渠道业务。在销售额增长上&#xff0c;通过线上的小程序、直播、平台渠道等方式&#xff0c;拓展流量变现渠道。在会员增长方面&#xff0c;通过多样的互动方式&#xff0c;全渠道触达消费者&am…

Power BI - 设置Waterfall Chart第一个Pillar的颜色

1.简单介绍 有的用户可能会单独设置Column Chart&#xff08;条形图&#xff09;的第一个柱子的颜色&#xff0c;如下图所示&#xff0c; 这种其实可以通过Column Chart的Conditional formating进行设置&#xff0c; - SWICH SELECTEDVALUE 或者也可以直接对单独的Column进行…

深入拆解TomcatJetty(一)

深入拆解Tomcat&Jetty&#xff08;一&#xff09; 专栏地址&#xff1a;https://time.geekbang.org/column/intro/100027701 1、Web容器是什么 早期的 Web 应用主要用于浏览新闻等静态页面&#xff0c;HTTP 服务器&#xff08;比如 Apache、Nginx&#xff09;向浏览器返…

Google play开发者账号被封,申诉就有机会,别不信

在谷歌上架&#xff0c;开发者账号被封对很多开发者来说已经是家常便饭了&#xff0c;虽说一直都有在流传申诉没有用。别灰心啊&#xff0c;申诉就有机会&#xff0c;不少开发者都申诉成功了。 尤其是用一个少一个、价值好几个w的老号&#xff0c;不申诉就认栽实在是太亏了&…

【黑马点评优化】之使用Caffeine+Redis实现应用级二层缓存

【黑马点评优化】之使用CaffeineRedis实现应用级二层缓存 1 缓存雪崩定义及解决方案2 为什么要使用多级缓存3 RedisCaffeine实现应用层二级缓存原理4 利用CaffeineRedis解决Redis突然宕机导致的缓存雪崩问题4.1 pom.xml文件引入相关依赖4.2 本地缓存配置类4.3 修改ShopServiceI…

大有期货携手云轴科技ZStack 获“鼎新杯”数字化转型典型案例二等奖

近日&#xff0c;由中国通信标准化协会主办、中国信息通信研究院&#xff08;简称“中国信通院”&#xff09;承办、中国通信企业协会支持的“2024数字化转型发展大会”在北京召开。本届大会以“拥抱数智化无限可能”为主题&#xff0c;会上公布了第三届“鼎新杯”数字化转型应…

Centos 7.9NFS搭建

原创作者&#xff1a;运维工程师 谢晋 Centos 7.9NFS搭建 NFS服务端安装客户机访问共享配置 NFS服务端安装 SSH连接系统登录到服务端安装nfs服务 # yum -y install nfs-utils2. 安装完成后&#xff0c;查看需要共享的目录&#xff0c;这边共享的是/home目录&#xff0c;如…

Selenium - 用这个力量做任何你想做的事情

Chrome DevTools 简介 Chrome DevTools 是一组直接内置在基于 Chromium 的浏览器&#xff08;如 Chrome、Opera 和 Microsoft Edge&#xff09;中的工具&#xff0c;用于帮助开发人员调试和研究网站。 借助 Chrome DevTools&#xff0c;开发人员可以更深入地访问网站&#xf…

苹果正式宣布:iPhone全面开放近场通信(Near Field Communication,简称NFC)【使用安全元件提供app内NFC数据交换功能】

文章目录 引言I iPhone的NFC功能开发者用户数据交换的体验革新安全与隐私II 知识扩展:近场通信(NFC)技术钱包NFC开关打开读取NFC标签(NFC tags )权限demo引言 2014年iPhone 6开始,苹果首次引入了NFC功能,但最初只允许自家的Apple Pay进行移动支付。慢慢地适配了交通卡,增…

RAG拉满-上下文embedding与大模型cache

无论怎么选择RAG的切分方案&#xff0c;仍然切分不准确。 最近&#xff0c;anthropics给出了补充上下文的embedding的方案&#xff0c;RAG有了新的进展和突破。 从最基础的向量查询&#xff0c;到上下文embedding&#xff0c;再到rerank的测试准确度都有了明显的改善&#xf…

Excel:vba实现合并工作簿中的表

A、B、C这三个工作簿的数据都在sheet1&#xff0c;表头一样 Sub MergeWorkbooks()Dim FolderPath As StringDim FileName As StringDim wb As WorkbookDim ws As WorksheetDim mainWb As WorkbookDim mainWs As WorksheetDim lastRow As LongDim lastcol As LongDim pasteRang…

双足机器人远程操作与动态运动同步研究

在当前的机器人技术中&#xff0c;双足机器人因其能够在复杂环境中灵活行动而备受关注。随着技术的进步&#xff0c;研究者们致力于开发能够与人类操作员实现高效同步的双足机器人&#xff0c;特别是在应对自然灾害或人为危险等紧急情况下的应用。 项目背景 尽管人工智能领域取…

Missing classes detected while running R8报错解决方案

Android 打包release版本时报错如下&#xff1a; > Task :printlib:minifyReleaseWithR8 FAILED AGPBI: {"kind":"error","text":"Missing classes detected while running R8. Please add the missing classes or apply additional ke…

在限制条件下求1+2+3+...+n

一&#xff1a;题目 二&#xff1a;代码 前提&#xff1a; A&#xff1a;静态成员和静态函数的性质 1.静态成员为所有类对象所共享&#xff0c;不属于某个具体的对象&#xff0c;存放在静态区 2. 静态成员变量必须在类外定义&#xff0c;定义时不添加static关键字&#xff0…

大模型生图安全疫苗注入赛题解析(DataWhale组队学习)

引言 大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年10月实践赛的大模型生图安全疫苗注入赛道&#xff1b;本文主要整理本次赛事的基本流程和优化方法。&#x1f495;&#x1f495;&#x1f60a; 一…

使用node.js控制CMD命令——修改本机IP地址

设置每次打开cmd命令行窗口都是以管理员身份运行&#xff1a; 1. 按下Ctrl Shift Esc键组合&#xff0c;打开任务管理器。 2. 在任务管理器中&#xff0c;点击“文件”菜单&#xff0c;选择“运行新任务”。 3. 在“创建新任务”对话框中&#xff0c;输入cmd&#xff0c;勾…

1.2024.10.17

2024.10.17 总体规划 总体规划 写这个合集的原因 记录自己入行之前成长过程。本人菜鸟一枚&#xff0c;大佬不喜勿喷。 目前的规划 更新频率 尽量一天一更&#xff0c;会更新之前发布的笔记&#xff0c;争取笔记更加完善。 学习方法 目标 通过面试&#xff0c;成功入行嵌…

移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——14.哈希(1)

移情别恋c ദ്ദി˶&#xff70;̀֊&#xff70;́ ) ——14.哈希(1) unordered系列关联式容器 在C98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可达到 l o g 2 N log_2 N log2​N&#xff0c;即最差情况下需要比较红黑树的高度次…