MyBatis 面试题(三)

server/2024/9/23 3:24:22/

1. MyBatis 为什么默认不会开启二级缓存?

MyBatis 默认不会开启二级缓存的原因主要有以下几点:

  1. 复杂性:二级缓存涉及到多个查询之间的数据共享,因此需要更多的逻辑来处理缓存的更新、失效和同步等问题。这种复杂性可能增加了系统的出错概率,并使得调试和维护变得更加困难。
  2. 一致性问题:在并发环境下,二级缓存可能引发数据一致性问题。例如,当两个线程同时读取并修改同一份数据时,如果其中一个线程的修改没有及时更新到缓存中,那么另一个线程读取到的数据可能就是旧的或不一致的。
  3. 性能考虑:虽然二级缓存可以提高某些查询的性能,但也可能对写入操作产生负面影响。因为每次写入操作后,都需要更新缓存,这可能会增加额外的开销。此外,如果缓存的数据量很大,那么缓存的创建、更新和销毁等操作可能会消耗更多的内存和CPU资源。
  4. 适用场景:不是所有的应用都需要或适合使用二级缓存。例如,对于实时性要求很高的应用,或者数据变化非常频繁的应用,使用二级缓存可能会导致数据延迟或不一致的问题。

2. MyBatis 中的缓存什么时候会被清理?

MyBatis 中的缓存分为一级缓存和二级缓存。这两种缓存的清理时机和策略是不同的。

一级缓存

一级缓存是 SqlSession 级别的缓存,也称为本地缓存。它是默认开启的,且不能被关闭。一级缓存的生命周期和 SqlSession 是一致的,当 SqlSession 关闭或清除时,一级缓存也就被清除了。

具体来说,以下几种情况会清理一级缓存:

  1. 当执行了增删改操作(insert、update、delete)后,一级缓存会立即被清理,这是因为这些操作可能会改变数据库中的数据,导致缓存中的数据不再准确。
  2. 当调用 SqlSession 的 clearCache() 方法时,也会清理一级缓存。
  3. 当 SqlSession 关闭时,一级缓存也会被清理。

二级缓存

二级缓存是 Mapper 级别的缓存,它可以跨多个 SqlSession 共享。二级缓存是可选的,需要手动开启。

二级缓存的清理时机则相对复杂一些。一般来说,以下几种情况会清理二级缓存:

  1. 当执行了增删改操作(insert、update、delete)后,MyBatis 会根据配置来决定是否清理二级缓存。如果配置为开启二级缓存,并且设置了缓存刷新策略为“FLUSH”或“EVICT”,那么二级缓存会被清理。否则,二级缓存中的数据不会被立即清理,而是会在下次查询时根据缓存的 key 来判断是否有效。
  2. 当调用 SqlSession 的 evictCache() 方法时,会清理当前 Mapper 的二级缓存。
  3. 当 Mapper 对应的 XML 映射文件被重新加载时(例如,修改了映射文件并重新部署应用),二级缓存也会被清理。
  4. 在某些情况下,如缓存过期、缓存大小超过限制等,二级缓存也可能被自动清理。这取决于具体的缓存实现和配置。

3. MyBatis 二级缓存清理策略有哪些?

MyBatis 的二级缓存清理策略主要包括以下几种:

  1. 基于引用类型的清理策略:这种策略主要依赖于 Java 的引用机制,包括软引用(SOFT)和弱引用(WEAK)。软引用缓存是一种基于 Java 软引用的缓存策略,当 JVM 内存不足时,才会清除缓存。而弱引用缓存则是基于 Java 弱引用的缓存策略,任何时候都可能被 JVM 清除。
  2. 基于时间的清理策略:虽然 MyBatis 的二级缓存本身并不直接支持基于时间的清理策略(如定期刷新或过期时间),但可以通过整合其他缓存框架(如 Ehcache)来实现这一功能。例如,在 Ehcache 中可以设置缓存的过期时间,当缓存对象超过设定的过期时间后,缓存会自动失效并被清理。
  3. 基于操作的清理策略:在某些情况下,可以根据特定的数据库操作来清理缓存。例如,当执行了增、删、改等操作时,可以手动清空缓存,以确保缓存中的数据与数据库中的数据保持一致。此外,也可以通过配置 MyBatis 的相关设置,使一级缓存在某些操作后自动失效,从而间接影响二级缓存的有效性。

4. MyBatis 接口绑定有哪几种方式?

MyBatis 接口绑定主要有以下几种方式:

  1. XML 映射文件方式:这是最常见的方式。我们需要为每个 mapper 接口创建一个对应的 XML 映射文件,然后在 XML 文件中定义 SQL 语句和结果映射。通过 XML 映射文件,我们将接口与 SQL 语句进行绑定。在 XML 文件中,我们使用 <mapper> 标签将接口与 XML 文件关联,使用 <select><insert><update><delete> 等标签定义相应的 SQL 操作,然后在接口中声明相匹配的方法。
  2. 注解方式:MyBatis 提供了一些注解,如 @Select@Insert@Update@Delete,我们可以直接在接口方法上使用这些注解,并在注解中编写 SQL 语句。这种方式省去了繁琐的 XML 配置,直接在接口方法上指定 SQL 语句,实现接口与 SQL 的绑定。
  3. 混合方式:在实际的项目中,我们一般会使用混合方式。即部分复杂的 SQL 语句使用 XML 映射文件方式,部分简单的 SQL 语句使用注解方式。这种方式结合了前两种方式的优点,既可以利用 XML 文件的灵活性,又可以利用注解的简洁性。

此外,虽然不直接属于接口绑定的方式,但值得一提的是 Provider 类方式。Provider 类是一个辅助类,可以在 XML 文件中使用动态 SQL 来构建 SQL 语句。这种方式提供了更大的灵活性,尤其是在需要构建复杂或动态 SQL 语句时。

每种方式都有其优缺点,选择哪种方式取决于项目的具体需求和开发团队的偏好。例如,对于复杂的 SQL 语句和需要高度定制化的场景,XML 映射文件方式可能更合适;而对于简单的 SQL 语句和追求简洁性的场景,注解方式可能更合适。混合方式则提供了更大的灵活性,可以根据实际需求选择使用。

5. MyBatis 有哪几种 SQL 编写形式?

MyBatis 提供了多种 SQL 编写形式,以适应不同场景和需求。以下是主要的几种形式:

  1. XML 形式:这是 MyBatis 最常见的 SQL 语句编写方式。在 XML 映射文件中,我们可以编写各种 CRUD 操作的 SQL 语句。这些 SQL 语句可以非常复杂,并且支持动态 SQL。例如,我们可以在 XML 映射文件中定义查询语句,通过 <select> 标签指定 SQL 语句,并通过参数和结果映射来实现与 Java 代码的交互。
  2. 注解形式:MyBatis 也支持在 Mapper 接口的方法上直接使用注解来编写 SQL 语句。这种方式适用于 SQL 语句比较简单的情况,例如简单的 CRUD 操作。通过使用如 @Select@Insert@Update@Delete 等注解,我们可以直接在接口方法上定义 SQL 语句,并指定参数和返回类型。

此外,MyBatis 还支持动态 SQL 的编写,以满足更复杂的业务逻辑需求。动态 SQL 可以根据传入的参数或条件动态地生成不同的 SQL 语句。MyBatis 提供了丰富的标签和元素来帮助我们编写动态 SQL,如 <if><choose><foreach><where> 等。这些标签可以在 XML 映射文件或注解中使用,以构建灵活的 SQL 语句。

综上所述,MyBatis 的 SQL 编写形式主要包括 XML 形式和注解形式,同时支持动态 SQL 的编写以满足更复杂的需求。在实际开发中,我们可以根据项目的具体需求和团队的编码习惯来选择适合的编写形式。

6. MyBatis 映射文件中有哪些顶级元素?

MyBatis 映射文件中的顶级元素主要包括以下几种:

  1. <mapper>:这是 SQL 映射文件的根元素,用于定义和组织整个映射文件。它标识了这是一个 MyBatis 的映射文件,并包含一个 namespace 属性,用于指定该映射文件对应的 Mapper 接口的全限定名。在该元素内部,可以定义其他顶级元素,如 <select><insert><update><delete> 等。
  2. <select>:用于编写查询语句的顶级元素。可以包含动态 SQL 元素,用于构建复杂的查询条件。它有一个 id 属性,用于唯一标识该查询语句,并与 Mapper 接口中的方法名对应。
  3. <insert>:用于编写插入语句的顶级元素。它也有一个 id 属性,用于标识该插入语句,并与 Mapper 接口中的方法名对应。
  4. <update>:用于编写更新语句的顶级元素,可以包含 UPDATE 和 INSERT 操作。同样具有 id 属性进行标识。
  5. <delete>:用于编写删除语句的顶级元素。也具有 id 属性进行标识。
  6. <resultMap>:用于定义查询结果的映射规则。它可以指定列名和 Java 对象属性的映射关系,以及嵌套的结果映射等。通过 <resultMap> 元素,可以精确地控制查询结果如何映射到 Java 对象上。
  7. <sql>:这是一个可重用的 SQL 语句块,可以在其他语句中引用。它允许你定义一段可重用的 SQL 代码片段,并在多个地方引用,以提高代码的可维护性和复用性。
  8. <cache><cache-ref>:这两个元素用于配置命名空间的缓存。<cache> 用于定义当前命名空间的缓存策略,而 <cache-ref> 用于引用其他命名空间的缓存配置。

此外,还有一些其他顶级元素,如 <parameterMap>(虽然已被废弃,建议使用行内参数映射),以及用于配置 MyBatis 行为的元素,如 <settings> 等。但上述列出的元素是 MyBatis 映射文件中最常见的顶级元素。

需要注意的是,随着 MyBatis 的版本更新,可能会引入新的顶级元素或废弃一些旧的元素,因此建议查阅官方文档以获取最准确和最新的信息。

7. MyBatis 映射时 A 引用了 B,如果 B 在 A 后面会怎样?

在 MyBatis 中,如果映射时 A 引用了 B,而 B 在 A 后面定义,这通常会导致一个问题:MyBatis 在解析映射文件或注解时,无法找到 B 的定义,因为它还没有被解析到。这会导致解析错误或运行时异常。

例如,考虑以下情况:

  1. 在一个 MyBatis 的 XML 映射文件中,你有两个 <resultMap> 标签,分别代表 A 和 B。A 的映射中引用了 B。
  2. 如果 B 的 <resultMap> 标签在 A 的后面,当 MyBatis 解析到 A 的映射时,它还没有遇到 B 的定义,因此无法解析 A 中对 B 的引用。

同样的情况也适用于注解方式。如果你在接口中定义了两个方法,A 方法使用注解引用了 B 方法的结果映射,而 B 方法的定义在 A 方法之后,那么在 MyBatis 尝试绑定这些方法时,也会遇到类似的问题。

为了解决这个问题,你需要确保引用的对象(在这个例子中是 B)在引用它的对象(A)之前被定义或解析。这通常意味着你需要调整映射文件或接口中方法的顺序,确保被引用的对象先被解析。

如果你正在使用注解,并且你的项目结构允许,你也可以考虑将共享的映射逻辑提取到一个单独的地方(如一个基类或配置文件中),这样就不需要在每个方法中重复定义它们,从而避免这种顺序依赖的问题。


http://www.ppmy.cn/server/11838.html

相关文章

OceanBase V4.2特性解析:用 Show Trace 快速定位数据库性能瓶颈

在数据库日常运维中&#xff0c;当遇到慢SQL问题时&#xff0c;若无法迅速查明原因&#xff0c;将极大地影响用户的使用感受&#xff0c;甚至可能引发业务或服务的中断。相较于单机数据库&#xff0c;分布式数据库系统因其涉及多个节点和多组件的协同工作&#xff0c;集群规模可…

十几个好用的学习以及AI网站

目录 1.识典古籍 2.华文慕课 3.历代人物 4.北大出版社电子书架 5.WaytoAGI 6.W3Schools 7.AI帮个忙 8.InsCode 9.文心一格 10.即使设计 11.AI绘画 12.无界AI 13.Midjourney中文站 14.其它 1.识典古籍 地址&#xff1a;识典古籍-古籍在线阅读平台 “识典古籍”是…

冯诺依曼与进程【Linux】

文章目录 冯诺依曼体系结构&#xff08;从硬件的角度描述&#xff09;冯诺依曼体系结构&#xff08;从软件的角度描述&#xff09;操作系统&#xff08;软件&#xff09;理解管理系统调用和库函数进程查看进程的两种方式 通过系统调用获取进程的PID和PPID通过系统调用创建进程-…

django忽略migrate

django migrate迁移时会依次执行四件事&#xff1a; 1、迁移判定&#xff0c;将你的项目中所有未迁移的变动文件进行迁移&#xff08;django会去查询django_migrations表判断你是否有新的迁移文件变动&#xff0c;若有新的迁移文件&#xff0c;则将变动加到django_migrations表…

Linux I2C(五) I2C字符设备的注册和使用

1&#xff0c;i2c-tools的使用 Android-i2ctools 下载&#xff1a; https://github.com/skyxiaoyan1/android-i2ctool 编译会生成五个工具&#xff1a;i2cdetect、i2cset、i2cget、i2cdump、i2ctransfer&#xff0c;拷贝到开发板中就可以使用。 i2cdetect&#xff1a;用于扫…

负载均衡原理|算法

负载均衡&#xff08;Load Balancing&#xff09;是一种计算机网络技术&#xff0c;其目的是将大量的并发请求或网络流量分散到多个服务器上&#xff0c;以此来提高服务的可用性、响应速度、以及系统的总体处理能力&#xff0c;同时减轻单个服务器的负担。负载均衡不仅能够避免…

【 书生·浦语大模型实战营】作业(五):LMDeploy 量化部署

【 书生浦语大模型实战营】作业&#xff08;五&#xff09;&#xff1a;LMDeploy 量化部署 &#x1f389;AI学习星球推荐&#xff1a; GoAI的学习社区 知识星球是一个致力于提供《机器学习 | 深度学习 | CV | NLP | 大模型 | 多模态 | AIGC 》各个最新AI方向综述、论文等成体系…

java文件拷贝的集中方式

四种拷贝方式 不同iobuffer iommap 零拷贝sendfile 零拷贝 核心代码 package com.itzhongzi.io;import java.io.*; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.Paths;/*** author Adminis…