一、什么是 MyBatis?
1、MyBatis 是一个半 ORM (对象关系映射) 框架,它内部封装了 JDBC, 开发时只需要关注 SQL 语句本身,不需要花费精力处理加载驱动、创建连接、创建 statement 等复杂的过程。程序员直接编写原生 SQL, 可以严格控制 SQL 执行性能,灵活度高。
2、MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO 映射数据库中记录。避免了大部分的 JDBC 代码和手动设置参数以及获取结果集。
二、MyBatis 的优点
1、基于 SQL 语句编程,只要你对 SQL 语句熟悉就已经成功了大半。因为 SQL 写在 XML 中,解除了 SQL 和程序代码的耦合,便于统一管理;提供 XML 标签,支持编写动态 SQL 语句,并且可以重用。
2、和 JDBC 相比,减少了大部分的冗余代码,消除了 JDBC 大量冗余的代码。不需要手动开关连接。
3、数据库兼容性特别高(因为 MyBatis 使用 JDBC 来连接数据库,所以只要 JDBC 支持的数据库 MyBatis 都支持)。
4、和 Spring 框架能够更好的集成。
三、MyBatis 框架的缺点
1、SQL 语句编写工作量较大。尤其当字段多、关联表多时。对开发人员编写 SQL 语句的功底有一定的要求。
2、SQL 语句依赖数据库,导致数据库移植性差,不能随意更换数据库。
四、MyBatis 和 Hibernate 有哪些不同?
1、MyBatis 和 Hibernate 不同的是,MyBatis 是一个半 ORM 框架,因为 MyBatis 需要程序员自己编写 SQL 语句。
2、MyBatis 直接编写原生 SQL, 可以严格控制 SQL 执行性能,灵活度高。适合对关系数据模型要求不高的软件开发,因为这种系统需求变化频繁,一旦需求变化需要迅速输出成果。但是 MyBatis 做不到数据库无关性,如果需要多种数据库连接,需要自定义多套 SQL 映射文件。
3、Hibernate 对象关系映射能力强,数据库无关性好,对于关系模型要求高的系统,Hibernate 可以节省很多代码。
五、#{} 和 ${} 的区别是什么?
{} 是预编译处理、${} 是字符串替换。MyBatis 在处理 #{} 时,会将 SQL 中的 #{} 替换为 ?号,调用 PreparedStatement 的 set 方法赋值。在处理 ${} 时,直接把 ${} 替换成实际的值。 使用 #{} 可以防止有效的 SQL 注入,提高系统的安全性。
六、MyBatis 是如何进行分页的?分页插件的原理是什么?
MyBatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分页,不是非物理分页。可以在 SQL 内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用 MyBatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的 SQL, 然后重写 SQL 根据 dialect 方言,添加对应的物理分页语句语句和物理分页参数。
七、MyBatis 的一级缓存、二级缓存
MyBatis 提供了两级缓存机制:一级缓存(Local Cache)和二级缓存(Secondary Cache)。这两级缓存机制在优化数据库查询、提高应用程序性能方面起着重要作用。
1、一级缓存(Local Cache)
一级缓存是 MyBatis 的默认缓存机制,它是基于 SqlSession 的,也就是说,每个 SqlSession 都会有一个独立的一级缓存区域。一级缓存的作用域是 SqlSession 级别的,当在同一个 SqlSession 中执行相同的查询时,MyBatis 会从一级缓存中直接返回结果,而不会再次查询数据库,从而提高了查询效率。
特点:
- 作用域:SqlSession 级别。
- 生命周期:与 SqlSession 生命周期相同,当 SqlSession 关闭或提交事务后,一级缓存中的数据会被清空。
- 数据共享:只在当前 SqlSession 内部共享数据。
注意事项:
- 当执行更新、删除、插入操作时,MyBatis 会清空当前 SqlSession 的一级缓存,以保证缓存数据与数据库的一致性。
- 不同的 SqlSession 之间的一级缓存是互相隔离的。
2、 二级缓存(Secondary Cache)
二级缓存是跨 SqlSession 的,它的作用域是 Mapper 映射文件级别的。多个 SqlSession 可以共享同一个二级缓存区域的数据。当多个 SqlSession 执行相同的查询时,如果二级缓存开启且数据未过期,MyBatis 会直接从二级缓存中返回结果,避免了多次查询数据库。
特点:
- 作用域:Mapper 映射文件级别(可以细粒度到 namespace)。
- 生命周期:依赖于 MyBatis 的配置文件和具体的缓存实现,可以配置缓存的过期时间等。
- 数据共享:多个 SqlSession 可以共享同一个二级缓存中的数据。
开启和使用二级缓存的步骤:
- 在 mybatis-config.xml 配置文件中开启二级缓存支持。
- 在 Mapper 映射文件中使用
<cache/>
标签来启用二级缓存。 - 序列化:由于二级缓存数据是跨 SqlSession 的,所以存储在二级缓存中的数据必须是可序列化的。
- 注意事项:当更新数据时,需要手动清空二级缓存或配置缓存策略(如使用 Redis、Ehcache 等外部缓存时)以保证数据一致性。
注意事项:
- 并非所有的查询都适合使用二级缓存,对于频繁变动的数据,使用二级缓存可能会带来数据一致性问题。
- 在分布式系统中,二级缓存可能需要配合分布式缓存解决方案(如 Redis)来实现。
综上所述,MyBatis 的一级缓存和二级缓存各有其特点和适用场景。在实际应用中,可以根据具体需求和数据特性来选择合适的缓存策略,以达到最优的性能和数据一致性。