面试必问:MyBatis 高频面试题!
这些都是面试常见的问题,看看下面的问题你都能答得上来吗?
1.什么是 MyBatis?它有哪些主要特性和优势?
2. mybatis 和数据库交互的原理?
3. mybatis 中
#{}、${}
的区别4. Mybatis 自带连接池都有什么?
5. Mybatis 的一级、二级缓存?
6. MyBatis 是如何进行分页的?分页插件的原理是什么?
7. mybatis 中常见的设计模式有哪些?
1. 什么是 MyBatis?它有哪些主要特性和优势?
MyBatis 是一个优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 消除了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的工作。MyBatis 可以使用简单的 XML 或注解来配置和映射原生类型、接口和 Java POJO 到数据库中的记录。
2. mybatis 和数据库交互的原理?
mybatis 和数据库交互主要分为几个阶段,第一步是 mybatis 会去加载配置文件,获取必要的基础的信息。然后创建出 sqlsessionfactory 工厂,工厂会帮助我们进行环境初始化,数据源加载等等。然后创建一个 sqlsession 对象,sqlsession 承担了与数据库交互的核心。每次执行数据库操作,可以从 sqlsession 里面获取到需要执行的 mapper。然后通过 mapper 开始执行 sql,获取数据。如果涉及事务也是 session 帮助我们来做事务提交或回滚的操作。
详细流程
初始化阶段
加载全局配置文件 (mybatis-config.xml)
使用 Resources.getResourceAsStream 方法读取 MyBatis 全局配置文件。
解析配置文件中的
<environments>、<mappers>
等节点,加载数据源、事务管理器和 Mapper 文件。
创建 SqlSessionFactory
使用 SqlSessionFactoryBuilder 构建 SqlSessionFactory 对象。
SqlSessionFactory 会根据配置文件初始化 MyBatis 环境,包括数据源、事务管理器和 Mapper 文件。
获取 SqlSession
打开 SqlSession
从 SqlSessionFactory 获取一个新的 SqlSession 实例。SqlSession 是 MyBatis 与数据库交互的核心对象,负责执行 SQL 语句、获取 Mapper 接口实例、管理事务等。
Mapper 接口操作
获取 Mapper 接口实例
通过 SqlSession 获取 Mapper 接口的实现类实例。MyBatis 会在运行时生成 Mapper 接口的实现类,并通过 SqlSession 获取其实例。
执行 SQL 语句
调用 Mapper 方法
调用 Mapper 接口的方法,例如 mapper.selectUserById(1);
参数处理
将方法参数转换为 SQL 语句中的占位符(如 #{id})所需的值。MyBatis 使用 TypeHandler 将 Java 类型转换为 JDBC 类型。
执行 SQL 语句
MyBatis 使用 JDBC 通过数据源执行 SQL 语句,数据库返回结果集。
结果映射
将 SQL 查询结果集映射为 Java 对象。根据映射文件或注解中的配置,将结果集中的数据映射到 Java 对象的属性中。
事务管理
提交事务
如果执行的数据操作需要提交事务,调用 session.commit();提交事务,提交事务会将所有未提交的更改保存到数据库。
回滚事务
如果操作过程中发生异常,需要回滚事务,调用 session.rollback();回滚事务,回滚事务会撤销所有未提交的更改。
关闭资源
关闭 SqlSession
操作完成后,调用 session.close();关闭 SqlSession,释放数据库连接。
3. mybatis 中#{}、${}
的区别
#{}
(预编译方式)
安全性:#{} 采用了预编译(PreparedStatement)的方式,有效防止了 SQL 注入。因为 MyBatis 会将
#{}
中的内容当作参数处理,而不是直接拼接到 SQL 语句中。处理方式:MyBatis 会为
#{}
中的内容生成一个参数占位符 ?,并使用 PreparedStatement 的 setXXX() 方法来设置参数值。因此,你不需要担心数据类型或引号问题。例子:
SELECT * FROM users WHERE id = #{userId}
,这条 SQL 语句在 MyBatis 中处理时,会将其转换为类似SELECT * FROM users WHERE id = ?
的形式,并通过 PreparedStatement 的 setInt() 或其他相关方法来设置 userId 的值。
${}
(字符串拼接方式)
安全性:
${}
是直接字符串拼接的方式,所以存在 SQL 注入的风险。如果参数来自用户输入或其他不可信的来源,那么使用${}
是非常危险的。处理方式:MyBatis 会直接将
${}
中的内容替换到 SQL 语句中。这意味着你需要自己处理数据类型、引号等问题。用途:虽然
${}
存在安全风险,但在某些场景下它是必要的。例如,当你要动态地构建表名或列名时,就必须使用${}
。例子:
SELECT * FROM ${tableName}
,这里的 tableName 是一个变量,MyBatis 会直接将其替换到 SQL 语句中。因此,如果你不能保证 tableName 的来源是可信的,那么这条 SQL 语句就存在 SQL 注入的风险。
4. Mybatis 自带连接池都有什么?
MyBatis 自带的连接池实现主要有两种:PooledDataSource 和 UnpooledDataSource。这两种连接池实现提供了不同的特性和使用场景。
UnpooledDataSource
UnpooledDataSource 是 MyBatis 提供的一个简单的、未池化的连接池实现。每次请求数据库连接时,UnpooledDataSource 都会创建一个新的连接,而不是从连接池中获取连接。这种实现适用于对性能要求不高的小型应用或测试环境。
PooledDataSource
PooledDataSource 是 MyBatis 提供的一个简单的连接池实现。它维护了一组数据库连接,以便在需要时快速提供连接,而不需要每次都创建新的连接。PooledDataSource 提供了基本的连接池功能,如连接池大小、连接超时等。
选择连接池实现
虽然 MyBatis 提供了内置的连接池实现,但在生产环境中,通常推荐使用功能更强大、性能更好的第三方连接池,例如:HikariCP:以高性能和低延迟著称。
Druid:一个成熟且广泛使用的连接池实现。
C3P0:一个功能丰富的连接池实现,适用于需要高级功能的场景。
使用第三方连接池时,可以通过配置 MyBatis 使用外部的数据源来替代内置的连接池。
5. Mybatis 的一级、二级缓存?
1. 一级缓存
MyBatis 的一级缓存 是用来减少数据库查询次数的,每个 SqlSession 都有自己的缓存。这个缓存默认是开启的,不需要额外配置。
缓存只在同一个 SqlSession 内有效,不同的 SqlSession 之间互不影响。执行增删改操作、调用 commit() 或 rollback() 方法,或者关闭 SqlSession 时,缓存会被清空。
当你执行查询操作时,MyBatis 会先看看缓存里有没有数据。如果有,就直接用缓存里的数据,不用再去查数据库。如果没有,就去查数据库,然后把结果放进缓存里。
MyBatis 用查询的 SQL 语句和参数作为缓存的键。
2. 二级缓存
mybatis 的二级缓存 ,相比与一级,其实更加的牛,相当于是跨 session 级别的缓存机制。
不同的 sqlsession 可以共享缓存,而在一级中,是彼此独立的。
二级缓存默认是关闭的,需要我们进行一波手动的开启。
二级缓存会将查询结果存储在内存中,以键值对的形式保存。Key 通常是查询语句及其参数的组合,Value 是查询结果。
当执行更新、插入或删除操作时,相关的缓存条目会被自动清除。可以集成第三方缓存框架,通过配置
<cache>
标签中的 type 属性来指定缓存提供者。
6. MyBatis 是如何进行分页的?分页插件的原理是什么?
Mybatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分页,而非物理分页,可以在 sql 内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用 Mybatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的 sql,然后重写 sql,根据 dialect 方言,添加对应的物理分页语句和物理分页参数。
例子:
select * from student
,拦截 sql 后重写为:select t.* from (select * from student) t limit 0, 10
7. mybatis 中常见的设计模式有哪些?
mybatis 中应用了大量的设计模式,常见的有工厂模式,单例模式,代理模式等,下面是详细的常见设计模式。
1. 工厂模式
在创建复杂对象时使用。MyBatis 使用 SqlSessionFactory 来创建 SqlSession 实例。SqlSessionFactory 本身是由 SqlSessionFactoryBuilder 创建的。
2. 单例模式
MyBatis 的 Configuration 类使用了单例模式,确保在一个 SqlSessionFactory 中只有一个 Configuration 实例。
3. 代理模式
为其他对象提供一种代理以控制对这个对象的访问。MyBatis 使用动态代理为 Mapper 接口生成实现类,从而在调用 Mapper 方法时执行 SQL 语句。
4. 模板方法模式
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。MyBatis 的 Executor 接口及其实现类使用了模板方法模式,定义了执行 SQL 语句的基本流程,而具体的执行细节由子类实现。
5. 建造者模式
SqlSessionFactoryBuilder:MyBatis 使用 SqlSessionFactoryBuilder 来构建 SqlSessionFactory 实例。
6. 装饰器模式(Decorator Pattern)
插件机制:MyBatis 的插件机制使用了装饰器模式,可以在执行器、参数处理器等核心组件上添加额外的功能。
7. 策略模式(Strategy Pattern)
缓存策略:MyBatis 的缓存机制使用了策略模式,不同的缓存实现可以互相替换。
8. 责任链模式(Chain of Responsibility Pattern)
拦截器链:MyBatis 的拦截器机制使用了责任链模式,可以在执行 SQL 语句的过程中通过一系列拦截器进行处理。
就业陪跑训练营学员投稿
欢迎关注 ❤
我们搞了一个免费的面试真题共享群,互通有无,一起刷题进步。
没准能让你能刷到自己意向公司的最新面试题呢。
感兴趣的朋友们可以加我微信:wangzhongyang1993,备注:infoq 面试群。
评论