【Mybatis】常见面试题汇总 共56题

文章目录

  • [1. 介绍下MyBatis?](#1. 介绍下MyBatis?)
  • [2. MyBatis 框架的应用场景?](#2. MyBatis 框架的应用场景?)
  • [3. MyBatis 有哪些优点?](#3. MyBatis 有哪些优点?)
  • [4. MyBatis 有哪些缺点?](#4. MyBatis 有哪些缺点?)
  • [5. MyBatis 用到了哪些设计模式?](#5. MyBatis 用到了哪些设计模式?)
  • [6. MyBatis常用注解有哪些?](#6. MyBatis常用注解有哪些?)
  • [7. MyBatis 有哪些核心组件?](#7. MyBatis 有哪些核心组件?)
  • [8. MyBatis编程步骤是什么样的?](#8. MyBatis编程步骤是什么样的?)
  • [9. MyBatis 和JDBC有什么区别?](#9. MyBatis 和JDBC有什么区别?)
  • [10. MyBatis 中的缓存机制有啥用?](#10. MyBatis 中的缓存机制有啥用?)
  • [11. MyBatis 一级缓存和二级缓存的区别?](#11. MyBatis 一级缓存和二级缓存的区别?)
  • [12. MyBatis 一级缓存和二级缓存是什么数据结构?](#12. MyBatis 一级缓存和二级缓存是什么数据结构?)
  • [13. MyBatis 中的缓存有哪些实现类型?](#13. MyBatis 中的缓存有哪些实现类型?)
  • [14. MyBatis 默认会开启缓存机制吗? 怎么开启?](#14. MyBatis 默认会开启缓存机制吗? 怎么开启?)
  • [15. MyBatis 为什么默认不会开启二级缓存?](#15. MyBatis 为什么默认不会开启二级缓存?)
  • [16. MyBatis 中的缓存什么时候会被清理?](#16. MyBatis 中的缓存什么时候会被清理?)
  • [17. MyBatis 二级缓存清理策略有哪些?](#17. MyBatis 二级缓存清理策略有哪些?)
  • [18. MyBatis 接口绑定有哪几种方式?](#18. MyBatis 接口绑定有哪几种方式?)
  • [19. MyBatis 有哪几种 SQL 编写形式?](#19. MyBatis 有哪几种 SQL 编写形式?)
  • [20. MyBatis 映射文件中有哪些顶级元素?](#20. MyBatis 映射文件中有哪些顶级元素?)
  • [21. MyBatis 映射时 A 引用了 B,如果 B 在 A 后面会怎样?](#21. MyBatis 映射时 A 引用了 B,如果 B 在 A 后面会怎样?)
  • [22. MyBatis 中 Mapper 接口的实现原理是?](#22. MyBatis 中 Mapper 接口的实现原理是?)
  • [23. MyBatis用注解绑定和用XML文件绑定有什么区别?](#23. MyBatis用注解绑定和用XML文件绑定有什么区别?)
  • [24. MyBatis通常一个 Xml 映射文件,都会写一个 Dao 接口与之对应, Dao 的工作原理,是否可以重载?](#24. MyBatis通常一个 Xml 映射文件,都会写一个 Dao 接口与之对应, Dao 的工作原理,是否可以重载?)
  • [25. MyBatis 中 Mapper 中的 SQL 语句可以重载吗?](#25. MyBatis 中 Mapper 中的 SQL 语句可以重载吗?)
  • [26. MyBatis动态 sql 是做什么的?都有哪些动态 sql?能简述一下动态 sql 的执行原理不?](#26. MyBatis动态 sql 是做什么的?都有哪些动态 sql?能简述一下动态 sql 的执行原理不?)
  • [27. MyBatis实体类中的属性名和表中的字段名不一样 ,怎么办?](#27. MyBatis实体类中的属性名和表中的字段名不一样 ,怎么办?)
  • [28. MyBatis 配置文件中的 SQL id 是否能重复?](#28. MyBatis 配置文件中的 SQL id 是否能重复?)
  • [29. MyBatis 支持哪些传参数的方法?](#29. MyBatis 支持哪些传参数的方法?)
  • [30. MyBatis 的$和# 传参的区别?](# 传参的区别?)
  • [31. MyBatis 可以映射到枚举类吗?](#31. MyBatis 可以映射到枚举类吗?)
  • [32. MyBatis 怎么封装动态 SQL?](#32. MyBatis 怎么封装动态 SQL?)
  • [33. MyBatis trim 标签有什么用?](#33. MyBatis trim 标签有什么用?)
  • [34. MyBatis where 标签有什么用?](#34. MyBatis where 标签有什么用?)
  • [35. MyBatis 是如何进行分页的?分页插件的原理是什么?](#35. MyBatis 是如何进行分页的?分页插件的原理是什么?)
  • [36. MyBatis 有几种分页方式?](#36. MyBatis 有几种分页方式?)
  • [37. MyBatis 逻辑分页和物理分页的区别是什么?](#37. MyBatis 逻辑分页和物理分页的区别是什么?)
  • [38. MyBatis 流式查询有什么用?](#38. MyBatis 流式查询有什么用?)
  • [39. MyBatis 模糊查询 like 语该怎么写?](#39. MyBatis 模糊查询 like 语该怎么写?)
  • [40. MyBatis 如何防止 SQL 注入?](#40. MyBatis 如何防止 SQL 注入?)
  • [41. MyBatis 如何获取自动生成的主键id?](#41. MyBatis 如何获取自动生成的主键id?)
  • [42. MyBatis 中`jdbcType` 和`javaType` 的区别?](#42. MyBatis 中jdbcTypejavaType 的区别?)
  • [43. 什么时候必须指定`jdbcType` 和`javaType`?](#43. 什么时候必须指定jdbcTypejavaType?)
  • [44. MyBatis 支持预编译吗? 怎么做?](#44. MyBatis 支持预编译吗? 怎么做?)
  • [45. MyBatis 中的事务管理方式?](#45. MyBatis 中的事务管理方式?)
  • [46. 怎么开启事务?](#46. 怎么开启事务?)
  • [47. MyBatis 事务和 Spring 事务有什么区别?](#47. MyBatis 事务和 Spring 事务有什么区别?)
  • [48. MyBatis 使用了哪些设计模式?](#48. MyBatis 使用了哪些设计模式?)
  • [49. 什么是 JPA?](#49. 什么是 JPA?)
  • [50. MyBatis 中 `StatementHandler` 和 `MappedStatement` 区别?](#50. MyBatis 中 StatementHandlerMappedStatement 区别?)
  • [51. MyBatis 常用的 `TypeHandler` 有哪些?](#51. MyBatis 常用的 TypeHandler 有哪些?)
  • [52. MyBatis 执行流程是怎样的?](#52. MyBatis 执行流程是怎样的?)
  • [53. MyBatis 中的 `SglSession` 是线程安全的吗?](#53. MyBatis 中的 SglSession 是线程安全的吗?)
  • [54. MyBatis 中的 `SglSession` 有哪些实现类?](#54. MyBatis 中的 SglSession 有哪些实现类?)
  • [55. MyBatis 中的 `DefaultSqlSession` 为什么不是线程安全的?](#55. MyBatis 中的 DefaultSqlSession 为什么不是线程安全的?)
  • [56. MyBatis 中 `SqlSessionTemplate` 与 `SqlSessionManager` 的区别?](#56. MyBatis 中 SqlSessionTemplateSqlSessionManager 的区别?)

1. 介绍下MyBatis?

MyBatis 是一个帮你简化数据库操作的工具,特别适合 Java 程序员。它的主要作用就是让你不用自己写一堆重复的数据库操作代码。简单来说,你只需要专注写 SQL 语句,MyBatis 会帮你把这些 SQL 和 Java 对象自动关联起来。

MyBatis 的亮点:

  1. 用原生 SQL:你可以直接写熟悉的 SQL 语句,不需要学新的语法,MyBatis 帮你处理把查询结果映射到 Java 对象的麻烦。
  2. 灵活好用:对于复杂查询,MyBatis 非常灵活,不像一些全自动的框架那样限制多。
  3. 配置简单:通过简单的 XML 文件或注解,你就能快速搞定 SQL 和 Java 之间的映射关系。
  4. 动态 SQL:你可以根据不同条件动态生成 SQL,处理一些有条件的查询特别方便。
  5. 和 Spring 兼容:MyBatis 可以很好地和 Spring 一起用,整合事务管理、依赖注入这些功能。

总之,MyBatis 适合那些想要灵活控制数据库查询,又不想写太多重复代码的人。

2. MyBatis 框架的应用场景?

  1. 复杂 SQL 查询:需要灵活编写复杂 SQL,避免 ORM 生成低效查询。
  2. 现有数据库集成:对已有数据库结构进行操作,不适合全面使用 ORM 的场景。
  3. 高性能需求:需要手动优化 SQL 查询性能时。
  4. 灵活控制:需要精确控制 SQL 语句和数据库操作的应用。

它特别适合那些对 SQL 有较高控制要求的项目。

3. MyBatis 有哪些优点?

  1. 原生 SQL 灵活:可以手写 SQL,处理复杂查询。
  2. 轻量易用:配置简单,学习成本低。
  3. 动态 SQL 支持:根据条件动态生成 SQL。
  4. 高性能:手动优化 SQL,性能可控。
  5. 现有数据库友好:适合已有复杂数据库的项目。

4. MyBatis 有哪些缺点?

  1. SQL 手动编写:需要开发者手写 SQL,增加工作量。
  2. 维护成本高:复杂项目中,管理大量 SQL 语句和映射关系可能变得困难。
  3. 缺少自动化:不像 ORM 框架,无法自动生成 SQL,手动处理对象与数据库的映射。
  4. SQL 与代码耦合:SQL 与 Java 代码耦合紧密,不利于数据库迁移或改动。

这些缺点使 MyBatis 在一些复杂或大规模项目中可能增加开发和维护难度。

5. MyBatis 用到了哪些设计模式?

MyBatis 采用了多种设计模式,帮助其实现灵活性和可扩展性,主要包括以下几种:

  1. 代理模式:MyBatis 使用代理模式(动态代理)来为 Mapper 接口生成实现类,处理 SQL 语句的执行,避免手动编写实现代码。

  2. 工厂模式 :MyBatis 使用工厂模式创建 SQLSession 对象,通过 SqlSessionFactory 来管理和提供 SQLSession。

  3. 单例模式SqlSessionFactory 使用单例模式确保工厂实例在应用中只有一个,方便统一管理数据库会话。

  4. 模板方法模式 :MyBatis 中的 Executor 类使用模板方法模式,提供执行 SQL 操作的通用流程,子类可以自定义具体实现。

  5. 建造者模式:在配置解析中,MyBatis 使用建造者模式生成复杂的对象,比如解析 XML 或注解并构建相应的映射配置。

6. MyBatis常用注解有哪些?

MyBatis 常用注解有:

  1. @Select:执行查询操作。
  2. @Insert:执行插入操作。
  3. @Update:执行更新操作。
  4. @Delete:执行删除操作。
  5. @Results:自定义结果集的映射。
  6. @Result:定义单个字段的映射关系。
  7. @Param:为 SQL 语句传递参数。

这些注解用于简化 SQL 操作,替代 XML 配置。

7. MyBatis 有哪些核心组件?

  1. SqlSessionFactory :创建和管理 SqlSession 对象的工厂。
  2. SqlSession:执行 SQL 语句的接口,管理数据库会话。
  3. Executor:负责执行 SQL 语句,管理缓存和事务。
  4. Mapper 接口:映射 SQL 语句与 Java 对象的方法接口。
  5. Configuration:全局配置类,包含 MyBatis 的所有配置信息。

8. MyBatis编程步骤是什么样的?

MyBatis 的编程步骤如下:

  1. 引入 MyBatis 依赖:在项目中配置 MyBatis 所需的依赖(如 Maven 中添加依赖项)。

  2. 配置 MyBatis 环境 :编写 mybatis-config.xml,配置数据库连接信息、别名、映射文件等。

  3. 编写 Mapper 文件

    • 使用 XML 文件编写 SQL 映射(或用注解方式)。
    • 定义接口(Mapper),与 SQL 映射文件中的 SQL 语句进行绑定。
  4. 创建 SqlSessionFactory :通过 SqlSessionFactoryBuilder 读取配置文件,生成 SqlSessionFactory

  5. 使用 SqlSession 操作数据库

    • 通过 SqlSessionFactory 获取 SqlSession
    • 调用 Mapper 接口执行增删改查操作。
    • 最后关闭 SqlSession 以释放资源。
  6. 处理结果:接收数据库操作返回的结果并处理。

9. MyBatis 和JDBC有什么区别?

MyBatis 和 JDBC 的区别主要有:

  1. 代码简化:MyBatis 简化了 JDBC 中繁琐的数据库操作代码,如连接管理、结果集处理,而 JDBC 需要手动编写大量代码。
  2. SQL 映射:MyBatis 自动将 SQL 结果映射到 Java 对象,JDBC 需要手动解析结果集。
  3. 动态 SQL 支持:MyBatis 支持动态生成 SQL,而 JDBC 中 SQL 是固定的,需要手动拼接。
  4. 事务管理:MyBatis 集成了事务管理,JDBC 需要手动处理事务。

总之,MyBatis 提供了更多的自动化和简化,而 JDBC 需要更多手动控制。

10. MyBatis 中的缓存机制有啥用?

MyBatis 中的缓存机制用于提高查询性能,减少对数据库的重复访问。它包括:

  1. 一级缓存:SqlSession 级别的缓存,默认开启,同一个 SqlSession 中的相同查询结果会缓存,减少重复查询。
  2. 二级缓存:Mapper 级别的缓存,可以跨 SqlSession,缓存同一个 Mapper 下的查询结果,需手动配置。

缓存机制减少数据库压力,提升应用性能。

11. MyBatis 一级缓存和二级缓存的区别?

MyBatis 一级缓存和二级缓存的区别:

  1. 缓存范围

    • 一级缓存:SqlSession 级别,默认开启,作用范围仅在同一个 SqlSession 内。
    • 二级缓存:Mapper 级别,可以跨 SqlSession,需手动配置。
  2. 生效时机

    • 一级缓存:每次使用同一个 SqlSession 执行相同查询时生效。
    • 二级缓存:不同 SqlSession 执行相同查询时也可生效。
  3. 失效条件

    • 一级缓存:SqlSession 关闭、提交或执行更新操作后失效。
    • 二级缓存:数据更新后失效,但配置持久化时缓存内容可保存。

12. MyBatis 一级缓存和二级缓存是什么数据结构?

MyBatis 一级缓存和二级缓存都使用 HashMap 作为数据结构来存储缓存数据。

13. MyBatis 中的缓存有哪些实现类型?

MyBatis 中的缓存实现类型主要有两种:

  1. PerpetualCache(永久缓存):默认的缓存实现,基于 HashMap 存储数据。
  2. Decorator 缓存 :通过装饰器模式增强缓存功能,包括:
    • LruCache:最近最少使用缓存淘汰策略。
    • FifoCache:先进先出缓存淘汰策略。
    • SoftCache:使用软引用,内存不足时自动回收。
    • WeakCache:使用弱引用,GC 后自动回收。
    • ScheduledCache:定时清理缓存。
    • SynchronizedCache:线程安全的缓存。
    • SerializedCache:序列化存储缓存内容。

这些类型提供了不同的缓存管理策略,适应不同的需求。

14. MyBatis 默认会开启缓存机制吗? 怎么开启?

MyBatis 默认开启一级缓存,一级缓存是 SqlSession 级别的,无需额外配置。

二级缓存默认关闭,需要手动开启。开启方法如下:

  1. mybatis-config.xml 中开启全局二级缓存:

    xml 复制代码
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
  2. 在对应的 Mapper 文件或 Mapper 接口中,通过 @CacheNamespace 注解或 XML 配置开启二级缓存:

    xml 复制代码
    <cache/>

这样 MyBatis 的二级缓存就会被启用。

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

MyBatis 默认不启用二级缓存,主要是出于以下考虑:

  1. 数据一致性问题:二级缓存是跨 SqlSession 的,数据更新后如果没有及时刷新缓存,可能导致脏数据(缓存与数据库不一致)。

  2. 内存占用:二级缓存存储在内存中,可能会占用较多内存资源,影响系统性能。

  3. 适用场景有限:二级缓存适合查询频繁、更新较少的场景,但并不适合所有项目,默认关闭可以避免不必要的性能开销。

因此,MyBatis 让开发者根据实际需求手动开启二级缓存。

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

MyBatis 中缓存的清理时机如下:

  1. 一级缓存(SqlSession 级别缓存):

    • SqlSession 关闭时,一级缓存会被清理。
    • 当在同一个 SqlSession 中执行 INSERTUPDATEDELETE 操作时,一级缓存会自动清空,确保数据一致性。
    • 当手动调用 clearCache() 方法时,也会清理一级缓存。
  2. 二级缓存(Mapper 级别缓存):

    • 当执行 INSERTUPDATEDELETE 操作时,二级缓存会被清除,确保数据一致性。
    • 二级缓存也可以通过自定义的缓存策略(如时间策略或大小限制)自动清理。
    • 如果使用了带有过期策略的缓存装饰器(如 ScheduledCache),缓存会根据设定的时间间隔清理。
    • 可以通过调用 clearCache() 方法手动清除二级缓存。

总结来说,缓存会在数据库发生修改操作或通过特定策略、手动清理时被清理,以保证数据的一致性和缓存的有效性。

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

MyBatis 二级缓存的清理策略主要有:

  1. 自动清理 :执行 INSERTUPDATEDELETE 操作时,缓存会自动清空。
  2. 基于时间的清理 :使用 ScheduledCache,按照设定的时间间隔清理缓存。
  3. 基于缓存淘汰策略
    • LruCache:最近最少使用的缓存项会被清除。
    • FifoCache:按照先入先出的顺序清理缓存。
  4. 手动清理 :可以通过调用 clearCache() 方法手动清除缓存。

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

MyBatis 接口绑定有两种方式:

  1. XML 文件方式:在 Mapper 接口中定义方法,并通过对应的 XML 文件绑定 SQL 语句。
  2. 注解方式 :直接在 Mapper 接口的方法上使用注解(如@Select@Insert@Update@Delete 等)编写 SQL,实现绑定。

这两种方式都可以将 SQL 语句与接口方法关联起来。

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

MyBatis 支持以下两种 SQL 编写形式:

  1. XML 文件形式:在 XML 文件中编写 SQL 语句,通过 Mapper 接口方法绑定。
  2. 注解形式 :直接在 Mapper 接口的方法上使用注解(如 @Select@Insert@Update@Delete)编写 SQL。

这两种方式都可以用于实现 SQL 操作,选择哪种形式取决于项目需求。

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

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

  1. <cache>:配置缓存策略。
  2. <cache-ref>:引用其他命名空间的缓存。
  3. <resultMap>:定义结果集映射规则。
  4. <sql>:定义可复用的 SQL 片段。
  5. <insert><update><delete><select>:定义 SQL 操作语句。

这些元素是 MyBatis 映射文件的核心组成部分。

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

在 MyBatis 映射文件中,如果映射 A 引用了映射 B,而 B 的定义在 A 之后,通常会导致 MyBatis 报错。因为 MyBatis 解析映射文件时是顺序进行的,当解析到 A 时,它会试图找到 B,但此时 B 还未被解析,因此会抛出 Invalid Reference 等类似的错误。

为避免这种问题,可以通过以下方式解决:

  1. 调整顺序 :确保 BA 之前定义。
  2. 使用命名空间引用 :将 B 放在其他映射文件中并通过命名空间引用,确保引用的映射在加载时已经存在。

顺序错误会直接影响 MyBatis 的解析,因此需要特别注意映射文件中引用的顺序。

22. MyBatis 中 Mapper 接口的实现原理是?

MyBatis 中 Mapper 接口的实现原理是通过动态代理生成接口的实现类。MyBatis 根据 Mapper 接口的方法签名自动生成 SQL 语句,并在运行时由 SqlSession 提供执行,返回对应的查询结果。这样开发者只需定义接口和 SQL 映射,不需要手动编写实现类。

23. MyBatis用注解绑定和用XML文件绑定有什么区别?

MyBatis 中注解绑定和 XML 文件绑定的区别如下:

  1. 注解绑定

    • SQL 语句直接写在 Mapper 接口的方法上,通过注解(如 @Select, @Insert, @Update, @Delete)定义。
    • 适合简单的 SQL 语句,代码集中在一个地方,维护方便。
    • 适合轻量级项目,不需要单独的 XML 文件。
  2. XML 文件绑定

    • SQL 语句保存在独立的 XML 文件中,通过 <select>, <insert>, <update>, <delete> 等标签定义。
    • 适合复杂 SQL,尤其是动态 SQL,XML 提供更灵活的控制。
    • 便于与业务逻辑分离,SQL 语句与代码解耦,易于维护和扩展。

简而言之,注解适合简单 SQL,XML 更适合复杂 SQL 和动态 SQL。

24. MyBatis通常一个 Xml 映射文件,都会写一个 Dao 接口与之对应, Dao 的工作原理,是否可以重载?

在 MyBatis 中,每个 XML 映射文件通常对应一个 DAO(Data Access Object)接口。DAO 接口的工作原理 是通过 MyBatis 的动态代理机制:MyBatis 自动生成 DAO 接口的实现类,通过 SqlSession 执行映射文件中的 SQL 语句,并将结果返回给调用者。

DAO 接口中的方法可以重载,即在同一个接口中,可以定义多个方法名相同但参数类型或数量不同的方法。然而,需要注意的是:

  • MyBatis 会根据方法签名(包括方法名和参数类型)确定调用哪个 SQL 语句。
  • 在 XML 映射文件中,每个重载的方法需要对应唯一的 <select>, <insert>, <update>, <delete> 标签,这些标签需要通过 id 唯一标识,每个 id 应与重载方法匹配。

因此,DAO 接口方法可以重载,但需要确保 XML 映射文件中的 id 能唯一标识每个方法。

25. MyBatis 中 Mapper 中的 SQL 语句可以重载吗?

MyBatis 中 SQL 语句不能直接重载 ,因为 SQL 是通过 Mapper 方法的名字和参数唯一映射的。如果方法重载,MyBatis 无法区分不同方法的 SQL。

解决方式:

  1. 使用不同的方法名。
  2. 使用动态 SQL 实现条件判断。
  3. 使用 @Param 区分参数。

重载本质上需要避免方法和 SQL 映射冲突。

26. MyBatis动态 sql 是做什么的?都有哪些动态 sql?能简述一下动态 sql 的执行原理不?

MyBatis 动态 SQL 用于根据条件动态生成 SQL 语句,避免写多个 SQL。

常用动态 SQL:

  1. <if>:条件判断。
  2. <choose> :类似 switch-case
  3. <trim>:去除多余的前后缀。
  4. <where> :自动添加 WHERE
  5. <set> :处理 UPDATE 语句。
  6. <foreach> :循环生成 SQL,常用于 IN 子句。

执行原理:根据传入参数,动态解析 SQL 标签生成最终 SQL,并执行。

27. MyBatis实体类中的属性名和表中的字段名不一样 ,怎么办?

在 MyBatis 中,如果实体类的属性名与数据库表中的字段名不一致,可以通过以下两种方式进行映射:

  1. 使用 @Results 注解

    在 Mapper 接口的方法上通过 @Results 注解手动指定实体类属性与数据库字段的对应关系。

    java 复制代码
    @Select("SELECT id, user_name FROM users")
    @Results({
        @Result(property = "userName", column = "user_name")
    })
    List<User> selectUsers();
  2. 在 XML 映射文件中使用 <resultMap>

    通过 XML 配置文件的 <resultMap> 元素将表字段与实体类属性进行映射。

    xml 复制代码
    <resultMap id="userMap" type="User">
        <result property="userName" column="user_name"/>
    </resultMap>
    
    <select id="selectUsers" resultMap="userMap">
        SELECT id, user_name FROM users
    </select>

这两种方式都可以解决实体类属性名和表字段名不一致的问题。

28. MyBatis 配置文件中的 SQL id 是否能重复?

在 MyBatis 配置文件中,SQL id 不能重复id 是每个 SQL 语句的唯一标识,用于在 Mapper 接口中引用特定的 SQL 语句。如果同一个 id 重复,MyBatis 会抛出异常,导致系统无法正常工作。

因此,确保每个 id 在同一 Mapper 文件中都是唯一的,以避免冲突。

29. MyBatis 支持哪些传参数的方法?

MyBatis 支持以下几种传参方法:

  1. 单个参数 :传递简单类型或对象,SQL 中用 #{param} 访问。

  2. 多个参数 :使用 @Param 注解,例如:

    java 复制代码
    List<User> findUser(@Param("id") int id, @Param("name") String name);
  3. 传递对象 :传递实体对象,SQL 中用 #{user.id} 访问属性。

  4. 使用 Map 传参 :通过 Map 传递参数,SQL 中用 #{key} 访问值。

这些方法提供了灵活的参数传递方式。

30. MyBatis 的$和# 传参的区别?

在 MyBatis 中,$# 传参的区别如下:

  1. #(安全的参数占位符)

    • 使用 # 时,MyBatis 会对传入的参数进行预处理,防止 SQL 注入。
    • 适用于 SQL 语句中的参数替换,例如:SELECT * FROM users WHERE id = #{id}
  2. $(直接字符串替换)

    • 使用 $ 时,MyBatis 直接将参数作为字符串替换,不进行任何处理
    • 适用于动态表名、列名等场景,例如:SELECT * FROM ${tableName}
    • 由于不安全,容易引发 SQL 注入,需谨慎使用。

31. MyBatis 可以映射到枚举类吗?

  1. 默认映射

    • 如果枚举名称与数据库字段值相同,MyBatis 会自动映射。
    java 复制代码
    public enum Status {
        ACTIVE, INACTIVE;
    }
  2. 自定义类型处理器

    • 如果需要自定义映射,可以实现 BaseTypeHandler
    java 复制代码
    public class StatusTypeHandler extends BaseTypeHandler<Status> {
        @Override
        public void setNonNullParameter(PreparedStatement ps, int i, Status parameter, JdbcType jdbcType) throws SQLException {
            ps.setString(i, parameter.name());
        }
        @Override
        public Status getNullableResult(ResultSet rs, String columnName) throws SQLException {
            return Status.valueOf(rs.getString(columnName));
        }
    }
  3. 在 XML 中指定类型处理器

    • 在 SQL 映射中指定使用自定义类型处理器。
    xml 复制代码
    <resultMap id="userMap" type="User">
        <result property="status" column="status_column" typeHandler="com.example.StatusTypeHandler"/>
    </resultMap>

总结:MyBatis 支持直接映射枚举或使用自定义类型处理器进行映射。

32. MyBatis 怎么封装动态 SQL?

在 MyBatis 中,封装动态 SQL 可以通过以下几种方式实现:

  1. XML 映射文件
    使用动态 SQL 标签,如 <if><choose>
xml 复制代码
<select id="findUsers" resultType="User">
    SELECT * FROM users
    WHERE 1=1
    <if test="name != null">
        AND name = #{name}
    </if>
    <if test="status != null">
        AND status = #{status}
    </if>
</select>
  1. 注解方式
    在 Mapper 接口中使用注解和脚本:
java 复制代码
@Select({
    "<script>",
    "SELECT * FROM users",
    "WHERE 1=1",
    "<if test='name != null'>",
    "AND name = #{name}",
    "</if>",
    "<if test='status != null'>",
    "AND status = #{status}",
    "</if>",
    "</script>"
})
List<User> findUsers(@Param("name") String name, @Param("status") String status);
  1. 查询条件对象
    定义一个查询条件对象,封装参数:
java 复制代码
public class UserQuery {
    private String name;
    private String status;
    // getters and setters
}

在 XML 中使用:

xml 复制代码
<select id="findUsers" resultType="User">
    SELECT * FROM users
    WHERE 1=1
    <if test="name != null">
        AND name = #{name}
    </if>
    <if test="status != null">
        AND status = #{status}
    </if>
</select>

33. MyBatis trim 标签有什么用?

MyBatis 中的 <trim> 标签用于处理 SQL 语句的前后缀,简化 SQL 的构建过程。它的主要作用是去除多余的分隔符(如 ANDOR),确保生成的 SQL 语句语法正确。

主要功能:

  1. 去除前缀

    • 可以在 SQL 语句开始前去除特定的前缀(如 ANDOR)。
  2. 去除后缀

    • 可以在 SQL 语句结束后去除特定的后缀(如 ANDOR)。
  3. 处理空值

    • 只有在满足某个条件时,才会添加对应的 SQL 部分。

示例:

xml 复制代码
<select id="findUsers" resultType="User">
    SELECT * FROM users
    <where>
        <trim prefix="WHERE" prefixOverrides="AND |OR ">
            <if test="name != null">
                AND name = #{name}
            </if>
            <if test="status != null">
                AND status = #{status}
            </if>
        </trim>
    </trim>
</select>

总结:<trim> 标签可以有效管理 SQL 语句中的多余分隔符,使动态 SQL 的构建更加灵活和简洁。

34. MyBatis where 标签有什么用?

MyBatis 中的 <where> 标签用于自动处理 SQL 语句中的 WHERE 子句,主要功能包括:

  1. 自动添加 WHERE :在有条件时自动插入 WHERE 关键字。
  2. 去除多余的 ANDOR :如果条件成立,自动去除多余的 ANDOR,确保 SQL 语法正确。

示例:

xml 复制代码
<select id="findUsers" resultType="User">
    SELECT * FROM users
    <where>
        <if test="name != null">
            AND name = #{name}
        </if>
        <if test="status != null">
            AND status = #{status}
        </if>
    </where>
</select>

35. MyBatis 是如何进行分页的?分页插件的原理是什么?

MyBatis 进行分页的常用方式是通过 分页插件 ,如 PageHelper。以下是其基本步骤和原理:

  1. 使用步骤
  • 添加依赖:在项目中添加分页插件的依赖。

  • 配置插件:在 MyBatis 配置文件中注册分页插件。

    xml 复制代码
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <property name="dialect" value="mysql"/> <!-- 数据库类型 -->
        </plugin>
    </plugins>
  • 调用分页方法:在查询前设置分页参数。

    java 复制代码
    PageHelper.startPage(pageNum, pageSize); // 设置当前页和每页大小
    List<User> users = userMapper.findAll(); // 查询数据
  1. 原理
  • 拦截器:分页插件通过 MyBatis 的插件机制拦截 SQL 执行。
  • SQL 修改 :插件修改原始 SQL,添加 LIMITOFFSET 以实现分页。
  • 结果封装:将结果封装成分页对象,包含总记录数和分页数据。

36. MyBatis 有几种分页方式?

MyBatis 有以下几种分页方式:

  1. 使用分页插件 :如 PageHelper,通过拦截器自动处理 SQL 进行分页。

  2. 手动分页 :在 SQL 中手动添加 LIMITOFFSET,根据传入的参数控制分页。

  3. 使用 RowBounds :使用 RowBounds 对象进行内存中的分页,不改变原始 SQL。

37. MyBatis 逻辑分页和物理分页的区别是什么?

  1. 逻辑分页
  • 定义:逻辑分页是指在应用层面进行分页处理,查询所有数据后再在内存中进行分页。
  • 特点
    • 所有数据一次性加载到内存中,适合数据量小的场景。
    • 可能会导致性能问题,因为需要处理完整的数据集。
  • 实现方式 :通过 RowBounds 或手动切分结果集。
  1. 物理分页
  • 定义:物理分页是指在数据库层面通过 SQL 语句进行分页,仅查询需要的数据。
  • 特点
    • 只查询当前页的数据,节省了内存和网络传输资源。
    • 更适合大数据量的场景,性能更优。
  • 实现方式 :通过 LIMITOFFSET 或使用分页插件(如 PageHelper)。
  1. 总结
  • 逻辑分页:在应用层处理,适合小数据集,可能影响性能。
  • 物理分页:在数据库层处理,适合大数据集,性能更佳。

38. MyBatis 流式查询有什么用?

  1. 减少内存占用

    逐行处理查询结果,避免一次性加载所有数据到内存中。

  2. 提高性能

    允许在结果加载时进行后续操作,缩短响应时间。

  3. 适用于大数据集

    有效解决无法一次性加载大数据集的问题。

  4. 示例

    使用 ResultHandler 逐行处理结果:

java 复制代码
sqlSession.select("namespace.selectStatement", new ResultHandler<User>() {
    @Override
    public void handleResult(ResultContext<? extends User> resultContext) {
        User user = resultContext.getResultObject();
        // 逐行处理 user 对象
    }
});

39. MyBatis 模糊查询 like 语该怎么写?

在 MyBatis 中,进行模糊查询可以使用 LIKE 关键字,通常结合 SQL 的通配符 % 来实现。

  1. XML 映射文件中的模糊查询
xml 复制代码
<select id="findUsersByName" resultType="User">
    SELECT * FROM users
    WHERE name LIKE CONCAT('%', #{name}, '%')
</select>
  1. 使用注解的方式
java 复制代码
@Select("SELECT * FROM users WHERE name LIKE CONCAT('%', #{name}, '%')")
List<User> findUsersByName(@Param("name") String name);
  1. 传递参数
    在调用时,将需要模糊匹配的字符串传入查询方法中:
java 复制代码
List<User> users = userMapper.findUsersByName("张三");

总结:使用 LIKE 结合 % 通配符,可以在 MyBatis 中实现模糊查询。通过 XML 或注解都可以轻松实现。

40. MyBatis 如何防止 SQL 注入?

MyBatis 防止 SQL 注入主要通过以下方式:

  1. 使用预编译语句 :通过参数化查询(#{})来绑定参数,避免直接拼接 SQL 字符串。

    xml 复制代码
    <select id="findUser" resultType="User">
        SELECT * FROM users WHERE username = #{username}
    </select>
  2. 避免直接拼接 SQL:不使用字符串拼接构建 SQL 语句,确保输入参数经过处理。

  3. 使用 MyBatis 的内置功能 :使用内置的 @Param 注解来安全地传递参数。

  4. 输入验证:在应用层进行输入验证,确保参数合法。

总结:通过参数化查询、避免拼接 SQL 和输入验证,MyBatis 有效防止 SQL 注入。

41. MyBatis 如何获取自动生成的主键id?

在 MyBatis 中获取自动生成的主键 ID 的方法如下:

  1. 使用 XML 映射
xml 复制代码
<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO users (username, password) VALUES (#{username}, #{password})
</insert>
  1. 使用注解
java 复制代码
@Insert("INSERT INTO users (username, password) VALUES (#{username}, #{password})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insertUser(User user);
  1. 获取 ID

插入后,自动生成的主键会赋值给对象的 id 属性:

java 复制代码
User user = new User();
user.setUsername("张三");
user.setPassword("password");
userMapper.insertUser(user);
Long generatedId = user.getId(); // 获取主键 ID

42. MyBatis 中jdbcTypejavaType 的区别?

  1. jdbcType
  • 定义:表示数据库中列的数据类型。
  • 用途:用于确定如何处理数据库中的数据,影响 SQL 语句的生成和执行。
  • 示例 :如 VARCHARINTEGERDATE 等。
  1. javaType
  • 定义:表示 Java 中对应的数据类型。
  • 用途:用于将数据库中的数据映射到 Java 对象的属性。
  • 示例 :如 StringIntegerDate 等。

总的来说,javaTypejdbcType都是用来处理数据类型的,javaType主要用来处理Java对象到数据库的映射,而jdbcType主要用来处理数据库类型和JDBC之间的关系。

43. 什么时候必须指定jdbcTypejavaType?

在 MyBatis 中,必须指定 jdbcTypejavaType 的情况主要有以下几种:

  1. jdbcType
  • NULL 值处理 :当字段可以为 NULL 时,必须显式指定 jdbcType,以便正确处理空值。
  • 特定类型映射 :对于一些特殊或不常用的数据类型,如 BLOBCLOB 等,建议指定 jdbcType 以确保正确处理。
  1. javaType
  • 复杂类型 :当字段类型是复杂类型(如自定义对象或集合)时,必须指定 javaType,以确保正确映射到 Java 类型。
  • 不匹配类型 :当数据库字段类型与 Java 类型不一致时,需要明确指定 javaType 以避免类型转换错误。

示例

xml 复制代码
<resultMap id="UserMap" type="User">
    <result property="id" column="id" jdbcType="INTEGER" javaType="java.lang.Integer"/>
    <result property="username" column="username" jdbcType="VARCHAR" javaType="java.lang.String"/>
    <result property="createdDate" column="created_date" jdbcType="TIMESTAMP" javaType="java.util.Date"/>
</resultMap>

总结:必须在处理 NULL 值、复杂类型或类型不匹配时显式指定 jdbcTypejavaType

44. MyBatis 支持预编译吗? 怎么做?

MyBatis 支持预编译,主要通过参数化查询来实现。具体做法如下:

  1. 使用参数化查询
    使用 #{} 语法指定参数,MyBatis 会自动进行预编译。

示例

XML 映射文件

xml 复制代码
<select id="findUserById" resultType="User">
    SELECT * FROM users WHERE id = #{id}
</select>

Mapper 接口

java 复制代码
User findUserById(@Param("id") int id);

总结:MyBatis 通过参数化查询(#{})实现预编译,确保 SQL 安全性和性能优化。

45. MyBatis 中的事务管理方式?

  1. 编程式事务管理
  • 通过 SqlSession 控制事务
    • 手动控制事务的开始、提交和回滚。
    • 适合需要细粒度控制的场景。
java 复制代码
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    // 开始事务
    // 执行操作
    sqlSession.commit(); // 提交事务
} catch (Exception e) {
    sqlSession.rollback(); // 回滚事务
} finally {
    sqlSession.close();
}
  1. 声明式事务管理
  • 结合 Spring 框架使用
    • 通过 @Transactional 注解自动管理事务。
    • 适合简单配置和一致性需求的场景。
java 复制代码
@Service
public class UserService {
    @Transactional
    public void addUser(User user) {
        // 执行数据库操作
    }
}

总结:MyBatis 提供编程式和声明式两种事务管理方式,编程式适合细粒度控制,声明式适合与 Spring 结合使用。

46. 怎么开启事务?

  1. 编程式事务管理
java 复制代码
SqlSession sqlSession = sqlSessionFactory.openSession(); // 开启事务
try {
    // 执行数据库操作
    sqlSession.commit(); // 提交事务
} catch (Exception e) {
    sqlSession.rollback(); // 回滚事务
} finally {
    sqlSession.close(); // 关闭会话
}
  1. 声明式事务管理(与 Spring 结合使用)
java 复制代码
@Service
public class UserService {
    @Transactional // 开启事务
    public void addUser(User user) {
        // 执行数据库操作
    }
}

总结

  • 编程式 :使用 SqlSession 手动管理事务。
  • 声明式 :使用 @Transactional 注解自动处理事务。

47. MyBatis 事务和 Spring 事务有什么区别?

  1. 事务管理方式
  • MyBatis 事务

    • 主要通过 SqlSession 手动管理,支持编程式事务控制。
    • 事务的开始、提交和回滚需要显式调用。
  • Spring 事务

    • 提供了声明式事务管理,可以通过 @Transactional 注解自动处理事务。
    • 可以与多种数据访问技术(如 JPA、Hibernate)结合使用。
  1. 事务范围
  • MyBatis 事务

    • 主要针对 MyBatis 的操作,事务的控制相对简单。
  • Spring 事务

    • 可以跨多个持久化层和服务层操作,支持更复杂的事务管理。
  1. 事务传播行为
  • MyBatis 事务

    • 没有内置的事务传播机制,需要手动实现。
  • Spring 事务

    • 提供多种事务传播行为(如 REQUIREDREQUIRES_NEW),可以灵活管理事务的传播和隔离级别。
  1. 集成支持
  • MyBatis 事务

    • 主要与 MyBatis 自身的会话管理结合。
  • Spring 事务

    • 支持多种持久化框架和不同的事务管理器,易于集成。

总结:

  • MyBatis 事务:手动控制,适合简单场景。
  • Spring 事务:声明式管理,支持复杂事务和多种持久化框架。

48. MyBatis 使用了哪些设计模式?

MyBatis 使用了以下设计模式:

  1. 代理模式:通过动态代理实现接口的实现,简化数据库操作。

  2. 工厂模式 :使用 SqlSessionFactory 创建 SqlSession,解耦对象创建过程。

  3. 单例模式SqlSessionFactory 通常采用单例模式,以确保只创建一个实例,优化资源使用。

  4. 模板方法模式:定义了操作的框架,允许子类(具体实现)重写某些步骤,但不改变算法的结构。

  5. 建造者模式:在创建复杂 SQL 语句时,通过构建器模式分步构造 SQL 语句。

总结:MyBatis 利用代理、工厂、单例、模板方法和建造者等设计模式,实现了灵活、可扩展和易于维护的数据库访问框架。

49. 什么是 JPA?

JPA(Java Persistence API)是 Java 平台的标准规范,用于管理 Java 对象与数据库之间的持久化。它主要特点包括:

  1. 对象关系映射(ORM):将 Java 对象映射到数据库表。
  2. 持久化上下文:管理实体生命周期,确保数据一致性。
  3. 查询语言:提供 JPQL(Java Persistence Query Language)用于查询实体。
  4. 事务管理:支持与 JTA 集成,管理事务。
  5. 厂商独立性:支持多种实现(如 Hibernate、EclipseLink)。

总结:JPA 简化了 Java 应用程序的数据库操作,提供标准化的持久化解决方案。

50. MyBatis 中 StatementHandlerMappedStatement 区别?

在 MyBatis 中,StatementHandlerMappedStatement 的区别如下:

  1. MappedStatement
  • 定义:表示 SQL 映射语句的元数据,包括 SQL 语句、参数类型、返回类型等信息。
  • 作用:用于配置和描述特定的 SQL 语句及其相关信息,通常在 XML 映射文件或注解中定义。
  1. StatementHandler
  • 定义 :用于执行 SQL 语句的接口,负责创建和管理 PreparedStatement
  • 作用:处理 SQL 执行的具体逻辑,包括参数设置、执行查询和处理结果集。

总结:

  • MappedStatement:用于描述 SQL 映射及其元数据。
  • StatementHandler:负责执行 SQL 语句的具体实现。

51. MyBatis 常用的 TypeHandler 有哪些?

MyBatis 常用的 TypeHandler 包括以下几种:

  1. BasicTypeHandler

    • 默认的类型处理器,处理基本类型(如 intString 等)与数据库类型之间的映射。
  2. EnumTypeHandler

    • 用于处理 Java 枚举类型与数据库值之间的映射。
  3. DateTypeHandler

    • 用于处理 java.util.Datejava.sql.Datejava.sql.Timestamp 等日期类型。
  4. JsonTypeHandler

    • 用于处理 JSON 字符串与 Java 对象之间的映射,通常与 JSON 库(如 Jackson 或 Gson)结合使用。
  5. BlobTypeHandler

    • 用于处理 BLOB(二进制大对象)数据类型的映射,适合存储二进制数据。
  6. ClobTypeHandler

    • 用于处理 CLOB(字符大对象)数据类型的映射,适合存储大文本数据。

52. MyBatis 执行流程是怎样的?

MyBatis 的执行流程如下:

  1. 创建 SqlSessionFactory

    • 从 MyBatis 配置文件中读取配置信息,创建 SqlSessionFactory 实例。
  2. 打开 SqlSession

    • 通过 SqlSessionFactory 打开一个 SqlSession,开始数据库操作。
  3. 映射语句的调用

    • 调用 Mapper 接口中的方法,传入参数,MyBatis 根据方法名查找对应的 MappedStatement
  4. 执行 SQL 语句

    • StatementHandler 根据 MappedStatement 创建 SQL 语句,并执行数据库操作(如查询、插入、更新等)。
  5. 处理结果

    • 将数据库返回的结果集映射为 Java 对象(实体),并返回给调用者。
  6. 提交或回滚事务

    • 如果是手动管理事务,根据操作结果选择提交或回滚事务。
  7. 关闭 SqlSession

    • 关闭 SqlSession,释放资源。

总结:MyBatis 的执行流程从创建 SqlSessionFactory 到关闭 SqlSession,包括 SQL 映射、执行和结果处理等步骤。

53. MyBatis 中的 SglSession 是线程安全的吗?

MyBatis 中的 SqlSession 不是线程安全 的。每个 SqlSession 实例应当在一个线程内独立使用,不能被多个线程共享。为了确保线程安全,通常的做法是每个线程都创建自己的 SqlSession 实例,使用完成后及时关闭。

54. MyBatis 中的 SglSession 有哪些实现类?

在 MyBatis 中,SqlSession 的主要实现类包括:

  1. DefaultSqlSession

    • MyBatis 默认的 SqlSession 实现,提供了基本的数据库操作功能。
  2. SqlSessionManager

    • 用于管理多个 SqlSession 的生命周期,支持事务控制。
  3. SqlSessionTemplate(Spring 集成):

    • 提供线程安全的 SqlSession 实现,适用于 Spring 环境,支持 Spring 的事务管理。

55. MyBatis 中的 DefaultSqlSession 为什么不是线程安全的?

DefaultSqlSession 在 MyBatis 中不是线程安全的,主要原因包括:

  1. 状态管理

    • DefaultSqlSession 维护了内部状态,如连接、事务和缓存等,这些状态在多个线程中共享可能导致数据不一致。
  2. 资源共享

    • 它包含对数据库连接的引用和其他资源,多个线程同时访问可能导致并发问题。
  3. 设计目的

    • SqlSession 设计为短暂的、一次性的会话,旨在处理单一数据库操作,适合在一个线程中使用。

56. MyBatis 中 SqlSessionTemplateSqlSessionManager 的区别?

SqlSessionTemplateSqlSessionManager 在 MyBatis 中的区别如下:

  1. 用途
  • SqlSessionTemplate

    • 用于在 Spring 环境中提供线程安全的 SqlSession,支持 Spring 的事务管理。适合在 Spring Bean 中使用。
  • SqlSessionManager

    • 用于管理多个 SqlSession 的生命周期,提供事务控制和批量处理功能。适合在需要手动管理 SqlSession 的场景中使用。
  1. 线程安全
  • SqlSessionTemplate

    • 线程安全,可以被多个线程共享,适合在多线程环境中使用。
  • SqlSessionManager

    • 本身并不保证线程安全,通常在每个线程中创建独立的 SqlSession
  1. 事务管理
  • SqlSessionTemplate

    • 自动与 Spring 的事务管理集成,简化事务处理。
  • SqlSessionManager

    • 提供手动的事务控制,适合复杂的事务管理场景。

总结:

  • SqlSessionTemplate:线程安全,适合 Spring 环境,自动集成事务管理。
  • SqlSessionManager :管理多个 SqlSession,不保证线程安全,适合手动事务控制。
相关推荐
xlsw_6 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
百度智能云技术站9 小时前
广告投放系统成本降低 70%+,基于 Redis 容量型数据库 PegaDB 的方案设计和业务实践
数据库·redis·oracle
梦想平凡11 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
夏木~12 小时前
Oracle 中什么情况下 可以使用 EXISTS 替代 IN 提高查询效率
数据库·oracle
吴冰_hogan14 小时前
MySQL InnoDB 存储引擎 Redo Log(重做日志)详解
数据库·oracle
cmdch201714 小时前
Mybatis加密解密查询操作(sql前),where要传入加密后的字段时遇到的问题
数据库·sql·mybatis
CodeCraft Studio14 小时前
【实用技能】如何在 SQL Server 中处理 Null 或空值?
数据库·oracle·sqlserver
武汉联从信息14 小时前
浅谈ORACLE中间件SOA BPM,IDM,OID,UCM,WebcenterPortal服务器如何做迁移切换
oracle
Elastic 中国社区官方博客15 小时前
Elasticsearch:什么是查询语言?
大数据·数据库·elasticsearch·搜索引擎·oracle
夜光小兔纸16 小时前
oracle dblink 的创建及使用
数据库·oracle