MyBatis 面试题(六)

embedded/2024/9/24 20:52:36/

1. MyBatis 有几种分页方式?

MyBatis 的分页方式主要可以分为两大类:逻辑分页和物理分页。

逻辑分页是一次性把全部数据查询加载进内存,然后再进行分页。这种方式减少了IO次数,适合频繁访问、数据量少的情况,但不适合大数据量,容易造成内存溢出。

物理分页则是利用数据库的特性进行分页,例如使用 LIMIT 语法。这种方式适合分页大数据量数据。

具体来说,MyBatis 的分页方式包括:

  1. 借助数组进行分页:首先查询出全部数据,然后在内存中通过数组或List进行截取,获取需要的部分。这种方式属于逻辑分页。
  2. 借助SQL语句进行分页:在SQL语句后面添加LIMIT分页语句,利用数据库的特性进行物理分页。这种方式直接在数据库层面进行操作,效率和性能都相对较高。
  3. 利用拦截器分页:通过拦截器给SQL语句末尾加上LIMIT语句来分页查询,实现物理分页。
  4. 利用RowBounds实现分页:需要一次获取所有符合条件的数据,然后在内存中对大数据进行操作即可实现分页效果。这种方式也属于逻辑分页,对于大数据量可能不太适用。
  5. 使用分页插件:例如PageHelper等分页插件,它们通过拦截MyBatis的SQL语句,自动添加分页相关的SQL片段,从而实现对查询结果的分页。这种方式既方便又灵活,是目前比较常用的分页方式。

在选择分页方式时,应根据具体的业务场景和需求来决定。对于数据量小、频繁访问的场景,可以选择逻辑分页;对于大数据量、需要高效分页的场景,则建议选择物理分页或使用分页插件。

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

MyBatis的逻辑分页和物理分页在分页的实现方式和数据库负担方面存在显著的区别。

逻辑分页主要依赖于代码,如MyBatis自带的RowBounds插件就是逻辑分页的一个例子。逻辑分页首先会一次性查询出所有的数据,然后再根据代码块的需要(例如需要获取第几页的数据,每页包含多少条数据)来筛选出合适的数据进行分页。这种方式在内存中操作数据,对数据库的访问次数相对较少,但由于需要一次性加载所有数据,如果数据量很大,可能会对内存造成较大的压力。

相比之下,物理分页则更侧重于数据库操作,依赖于数据库提供的分页功能。例如,MySQL数据库提供了“limit”关键字来实现分页,程序员只需要编写带有这些关键字的SQL语句,数据库返回的数据就是分页结果。物理分页每次分页都需要访问数据库,因此它对数据库的负担较大,但由于每次只处理一部分数据,对内存的压力相对较小。

总结来说,逻辑分页和物理分页的主要区别在于:逻辑分页在内存中操作数据,对数据库访问次数少但可能消耗大量内存;而物理分页直接在数据库层面实现分页,每次分页都需要访问数据库但对内存压力较小。在实际应用中,应根据具体需求和场景选择合适的分页方式。

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

MyBatis 流式查询是一种优化查询的方法,主要用于处理大量数据,以降低内存占用和提高查询速度。在流式查询模式下,查询结果不是一次性加载到内存中,而是逐条从数据库服务器传输到客户端。这意味着应用可以从迭代器中每次取一条查询结果,而不是一次性处理整个结果集。这种方式的优点在于,它允许在内存不足以容纳全部结果集的情况下,仍然能够处理大量数据。

具体来说,流式查询的好处主要体现在以下几个方面:

  1. 降低内存使用:通过流式查询,应用程序不需要一次性加载整个结果集到内存中,从而减少了内存的使用。这在处理海量数据时尤为重要,可以有效避免内存溢出等问题。
  2. 提高查询效率:对于大数据量的查询,一次性加载整个结果集可能会消耗大量的时间和资源。而流式查询允许应用程序逐步处理查询结果,从而提高了查询效率。
  3. 适用于特定场景:流式查询特别适用于需要处理大量数据但不需要同时访问所有数据的情况,例如数据导出、日志分析等。

需要注意的是,在使用流式查询时,数据库连接通常保持打开状态,因此应用需要在取完数据后自己关闭数据库连接,因为数据库访问框架不再负责关闭连接。此外,使用流式查询时,ResultSet对象的一些方法可能会失效,比如absolute()、last()、previous()、beforeFirst()等方法。

总的来说,MyBatis 流式查询是一个数据库访问框架必须具备的功能,它能够在处理大量数据时提供高效的解决方案,降低内存使用并提高查询速度。

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

在 MyBatis 中进行模糊查询时,通常使用 SQL 的 LIKE 语句配合通配符 % 来实现。通配符 %LIKE 语句中表示任意长度的字符序列(包括零个字符)。

下面是一个在 MyBatis 中使用 LIKE 进行模糊查询的示例:

首先,假设你有一个名为 User 的实体类,它有一个属性 name。你希望根据 name 的部分值来查询用户。

  1. Mapper XML 文件

在 MyBatis 的 Mapper XML 文件中,你可以这样写 SQL 语句:

<select id="findUsersByName" resultType="User">SELECT * FROM userWHERE name LIKE CONCAT('%', #{name}, '%')
</select>

这里使用了 CONCAT 函数来拼接 % 和传入的参数 #{name}。这样,无论传入的 name 是什么,它都会被包裹在 % 之间,从而实现模糊查询。

  1. Mapper 接口

对应的 Mapper 接口方法可能如下:

public interface UserMapper {List<User> findUsersByName(String name);
}
  1. 在 Service 或 Controller 中调用

然后,在你的 Service 或 Controller 中,你可以调用这个 Mapper 方法来进行查询:

@Autowired
private UserMapper userMapper;public List<User> searchUsers(String searchTerm) {return userMapper.findUsersByName(searchTerm);
}

注意:在实际应用中,为了防止 SQL 注入攻击,你应该始终使用预编译的 SQL 语句(即使用 #{} 来绑定参数),而不是直接将参数拼接到 SQL 语句中(即使用 ${})。在上面的示例中,我们使用了 #{} 来绑定 name 参数,这是安全的做法。

5. MyBatis 如何防止 SQL 注入?

MyBatis 通过预编译(PreparedStatement)的方式来防止 SQL 注入。预编译的 SQL 语句在执行时会将参数值作为数据而不是 SQL 的一部分来处理,从而避免了 SQL 注入的风险。

具体来说,MyBatis 在处理 SQL 语句时,会将 SQL 语句中的参数用占位符(通常是 #{})替代,然后在执行 SQL 语句之前,通过 PreparedStatement 对象设置参数值。由于 PreparedStatement 对象会对参数值进行转义和处理,因此即使参数值中包含 SQL 注入攻击的代码,也不会被解析为 SQL 语句的一部分,从而避免了 SQL 注入。

例如,在 MyBatis 的 Mapper XML 文件中,我们可以这样写 SQL 语句:

<select id="selectUserById" resultType="User">SELECT * FROM user WHERE id = #{id}
</select>

在这个例子中,#{id} 是一个占位符,MyBatis 会将它替换为实际的参数值,并使用 PreparedStatement 来设置这个参数。这样,即使 id 的值是一个恶意构造的 SQL 语句片段,它也不会被解析为 SQL 的一部分,因此无法执行 SQL 注入攻击。

需要注意的是,虽然 MyBatis 本身已经提供了防止 SQL 注入的机制,但是在编写 SQL 语句时仍然需要谨慎。特别是当使用 ${} 来直接插入字符串时,需要特别小心,因为这种方式不会进行预编译,如果插入的字符串中包含恶意 SQL 代码,就可能导致 SQL 注入。因此,除非有特别的需求,否则一般推荐使用 #{} 来插入参数。

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

在 MyBatis 中,当你插入一条记录到数据库,并且这条记录有一个自动生成的主键(例如,使用 MySQL 的 AUTO_INCREMENT 或者其他数据库的类似机制),你可以通过几种不同的方式来获取这个自动生成的主键 ID。

以下是几种常见的方法:

1. 使用 useGeneratedKeyskeyProperty

你可以在 MyBatis 的 <insert> 标签中使用 useGeneratedKeyskeyProperty 属性来告诉 MyBatis 你想要获取自动生成的主键。

<insert id="insertUser" parameterType="com.example.User" useGeneratedKeys="true" keyProperty="id">INSERT INTO user (name, email) VALUES (#{name}, #{email})
</insert>

在这个例子中,useGeneratedKeys="true" 告诉 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来获取自动生成的主键。keyProperty="id" 指定了哪个属性应该被用来接收这个主键值。在这个例子中,idUser 类的一个属性。

执行插入操作后,你可以直接从传入的 User 对象中获取这个 ID:

User user = new User();
user.setName("John Doe");
user.setEmail("johndoe@example.com");
userMapper.insertUser(user);
Long generatedId = user.getId(); // 这里就是自动生成的主键 ID
2. 使用 selectKey

另一种方法是使用 <selectKey> 标签。这通常在你需要执行一个额外的查询来获取主键时使用,例如在非自增主键的场景中。

<insert id="insertUser" parameterType="com.example.User"><selectKey keyProperty="id" resultType="java.lang.Long" order="AFTER">SELECT LAST_INSERT_ID()</selectKey>INSERT INTO user (name, email) VALUES (#{name}, #{email})
</insert>

在这个例子中,<selectKey> 标签执行了一个查询来获取最后一个插入的 ID(这里假设你使用的是 MySQL)。order="AFTER" 表示在插入操作之后执行这个查询。查询的结果将被设置到 User 对象的 id 属性中。

注意事项:
  • 确保你的数据库驱动和 JDBC 版本支持获取自动生成的主键。大多数现代驱动和 JDBC 版本都支持这个功能。
  • 如果你的数据库表使用了复合主键或者没有使用自动生成的主键机制,那么你可能需要采用其他策略来获取主键。
  • 在某些情况下,你可能需要根据你的数据库和 JDBC 驱动的具体行为来调整这些设置。

7. MyBatis 中jdbcType 和javaType 的区别?

在 MyBatis 中,jdbcTypejavaType 是两个重要的属性,用于指定参数或结果集中字段的数据库类型和 Java 类型。它们的主要区别体现在它们所代表的类型层面和用途上。

jdbcType

jdbcType 是 JDBC 的类型,它表示数据库中的数据类型。当执行 SQL 语句时,MyBatis 会使用 jdbcType 来告诉 JDBC 驱动如何正确地设置或获取参数值或结果集字段的值。jdbcType 是数据库层面上的数据类型,例如 VARCHARINTEGERDATE 等。

在 MyBatis 的映射文件或注解中,你可能会在 <parameterMap><resultMap><insert><update><select> 等标签中看到 jdbcType 属性。它确保 MyBatis 能够正确地将 Java 对象转换为对应的数据库类型,或者将数据库字段的值转换为 Java 对象。

javaType

javaType 是 Java 的类型,它表示 Java 程序中使用的数据类型。在 MyBatis 中,javaType 用于指定 Java 对象的类型,以便 MyBatis 能够正确地将数据库字段的值映射到 Java 对象的属性上,或者将 Java 对象的属性值映射到 SQL 语句的参数中。

javaType 通常用于指定 Java 的基本类型(如 intString)或自定义的 Java 类型(如自定义的实体类)。在 MyBatis 的映射文件或注解中,javaType 常常与 resultMapparameterType 一起使用,以确保数据在 Java 和数据库之间能够正确地转换。

示例

假设你有一个 Java 实体类 User,其中有一个 id 属性,该属性在数据库中是一个整数类型。在 MyBatis 的映射文件中,你可能会这样指定 jdbcTypejavaType

<resultMap id="UserResult" type="com.example.User"><result property="id" column="user_id" jdbcType="INTEGER" javaType="java.lang.Integer"/>
</resultMap>

在这个示例中,jdbcType="INTEGER" 告诉 MyBatis 数据库中的 user_id 字段是一个整数类型,而 javaType="java.lang.Integer" 则告诉 MyBatis 在 Java 中应该将这个字段的值映射到 Integer 类型的属性上。

总结

jdbcTypejavaType 的主要区别在于它们分别代表了数据库层面和 Java 层面的数据类型。在 MyBatis 中,正确设置这两个属性对于确保数据能够正确地在 Java 程序和数据库之间转换是非常重要的。


http://www.ppmy.cn/embedded/9679.html

相关文章

“EDM邮件营销”如何构建企业获客增长新赛道

在这个瞬息万变的数字时代&#xff0c;企业的营销策略不断进化&#xff0c;以求在激烈的市场竞争中脱颖而出。其中&#xff0c;“EDM&#xff08;Electronic Direct Mail&#xff09;邮件营销”作为一项经典且高效的营销手段&#xff0c;正借助先进的技术力量&#xff0c;重新焕…

CSS布局 Flex 和 Grid

在 CSS 中&#xff0c;理解 flex 和 Grid 布局非常重要&#xff0c;今天把这两个重要知识点回顾一下。 Flexbox 弹性盒子布局 弹性布局支持 flex、inline-flex&#xff0c;支持块和内联。 容器 轴的概念&#xff0c;在 Flexbox&#xff0c;有主轴和侧轴的概念&#xff0c;轴…

HarmonyOS ArkUI实战开发-窗口模块(Window)

窗口模块用于在同一物理屏幕上&#xff0c;提供多个应用界面显示、交互的机制。 对应用开发者而言&#xff0c;窗口模块提供了界面显示和交互能力。对于终端用户而言&#xff0c;窗口模块提供了控制应用界面的方式。对于操作系统而言&#xff0c;窗口模块提供了不同应用界面的…

【Interconnection Networks 互连网络】Torus 网络拓扑

1. Torus 网络拓扑2. Torus 网络拓扑结构References 1. Torus 网络拓扑 Torus 和 Mesh 网络拓扑&#xff0c;又可以称为 k-ary n-cubes&#xff0c;在规则的 n 维网格中包裹着 N k^n 个节点&#xff0c;每个维度都有 k 个节点&#xff0c;并且最近邻居之间有通道。k-ary n-c…

Linux 目录操作函数

目录操作函数 ls -l 可以查看目录中文件的信息&#xff0c;比如&#xff1a; petriXX:~/lesson01/05_io/目录操作函数$ ls -l a.txt -rw-r--r-- 1 petri petri 0 Apr 22 18:51 a.txtLinux系统中的目录操作函数&#xff1a; int rename(const char *oldpath, const char *new…

通过Docker新建并使用MySQL数据库

1. 安装Docker 确保您的系统上已经安装了Docker。可以通过以下命令检查Docker是否安装并运行&#xff1a; systemctl status docker如果没有安装或运行&#xff0c;请按照官方文档进行安装和启动。 2. 拉取MySQL镜像 从Docker Hub拉取MySQL官方镜像。这里以MySQL 5.7版本为…

一个typescript 5 + rollup 4 打包lib模板仓库实现

前言 昨天在写点什么东西的时候&#xff0c;发现有些逻辑可以搞成一个 npm 模块。 找了下看看&#xff0c;有没有什么好用现成模板用于开发。。发现并没有&#xff1b; 那有需求就解决需求。。 需求 基于当前的流行技术栈选型(rollup 4.x typescript 5.x)提供一个最小化模…

Leetcode 86. 分隔链表

题目链接&#xff1a; 86. 分隔链表 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/partition-list/description/ 题目&#xff1a; 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出…