【面试官】Mybatis缓存有什么问题吗?

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 面试官:你说下对MyBatis的理解?面试官:那SqlSession知道吧?面试官:Mybatis的缓存有哪几种?面试官:那Mybatis缓存有什么问题吗?面试官:Mybatis分页插件是怎么
  • 面试官:你说下对MyBatis的理解?
  • 面试官:那SqlSession知道吧?
  • 面试官:Mybatis的缓存有哪几种?
  • 面试官:那Mybatis缓存有什么问题吗?
  • 面试官:Mybatis分页插件是怎么实现的?

大家好,我是南哥。

一个Java学习与进阶的领路人,今天继续给大家带来新的一篇Java进阶指南。

本文收录在我开源的《Java学习进阶指南》中,一份涵盖了你学习Java、成为更好的Java选手所需掌握的核心知识、面试重点。相信能帮助到大家在Java成长路上不迷茫。南哥希望收到大家的 ⭐ Star ⭐支持,这是我创作的最大动力。GitHub地址:https://github.com/hdgaadd/JavaProGuide

文章目录

  1. Mybatis概要
    1. Mybatis理解
    2. SqlSession是什么
  2. Mybatis缓存
    1. Mybatis缓存分类
    2. Mybatis缓存局限性
  3. Mybatis分页插件

1. Mybatis概要

1.1 Mybatis理解

面试官:你说下对MyBatis的理解?

如果没有MyBatis的支持,大家是怎么实现通过程序控制数据库的?首先我们需要为程序引入MySQL连接依赖mysql-connector.jar,加载数据库JDBC驱动,接着创建数据库连接对象Connection、SQL语句执行器Statement,再把SQL语句发送到MySQL执行,最后关闭SQL语句执行器和数据库连接对象。

整个过程是比较繁琐的,这是通过JDBC操作MySQL必走的过程。可实际开发可给不了你那么多时间,如果大家非要用JDBC去写大量的冗余代码也可以,能抗住催你开发进度的压力就行。

这是JDBC操作的过程。

public class JDBCController {
   
   
    private static final String db_url = "jdbc:mysql://localhost:3306/db_user";
    private static final String user = "root";
    private static final String password = "root";

    public static void main(String[] args) {
   
   
        Connection connection = null;
        Statement statement = null;
        String sql = "select * from user order by id desc";
        try {
   
   
            connection = DriverManager.getConnection(db_url, user, password);
            statement = connection.createStatement();
            int result = statement.executeUpdate(sql);
            System.out.println(result);
        } catch (SQLException e) {
   
   
            throw new RuntimeException(e);
        } finally {
   
   
            if (statement != null) {
   
   
                try {
   
   
                    statement.close();
                } catch (SQLException e) {
   
   
                    throw new RuntimeException(e);
                }
            }
            if (connection != null) {
   
   
                try {
   
   
                    connection.close();
                } catch (SQLException e) {
   
   
                    throw new RuntimeException(e);
                }
            }
        }
    }
}

MyBatis能帮助我们什么?早在2002年,MyBatis的前身iBatis诞生,并于2010年改名为MyBatis。该框架引入了SQL映射作为持久层开发的一种方法,也就是说我们不需要把SQL耦合在代码里,只需要把SQL语句单独写在XML配置文件中。

以下是MyBatis编写SQL的写法。SQL的编写已经和程序运行分离开,消除了大量JDBC冗余代码,同时MyBatis还能和Spring框架集成。整个SQL编写的流程变得更加灵活也更加规范化

@Mapper
public interface UserMapper extends BatchMapper<UserDO> {
   
   
    List<UserDO> selectAllUser();
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.JavaGetOffer.UserDO">

    <select id="selectAllUser" resultType="org.JavaGetOffer.UserDO">
        select * from user order by id desc
    </select>

</mapper>

1.2 SqlSession是什么

面试官:那SqlSession知道吧?

从我们偷偷访问某个小网站开始,到我们不耐烦地关闭浏览器或者退出登录时,我们作为用户和网站的一次会话就结束了。MyBaits框架要访问数据库同样要与数据库建立通信桥梁,而SqlSession对象表示的就是MyBaits框架与数据库建立的会话

我们可以利用SqlSession来操作数据库,如下代码。

    @Test
    public void testMybatis() throws IOException {
   
   
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<UserDO> userList = userMapper.listAllUser();
        System.out.println(JSON.toJSONString(userList));
    }

2. Mybatis缓存

2.1 Mybatis缓存分类

面试官:Mybatis的缓存有哪几种?

软件系统合理使用缓存有一个好处。有了缓存,在原始数据没有更新的情况下,我们不需要重新再去获取一遍数据,这也减少了数据库IO,达到提升数据库性能的目的。

MyBatis同样提供了两个级别的缓存,一级缓存是基于上文提到的SqlSession实现,二级缓存是基于Mapper实现。

一级缓存作用在同一个SqlSession对象中,当SqlSession对象失效则一级缓存也跟着失效。我们梳理下一级缓存的生命周期。首先第一次查询时会把查询结果写入SqlSession缓存,如果第二次查询时原始数据没有改变则会读取缓存,但如果是修改、删除、添加语句的执行,那SqlSession缓存会被全部清空掉,这也是为了防止脏读的出现。

一级缓存缓存底层使用的是一个简单的Map数据结构来存储缓存,其中key为SQL + 参数、val为查询结果集。一级缓存的生命周期如下。

在这里插入图片描述

二级缓存的作用域是同一个命名空间namespace的Mapper对象,也就是说同一个Mapper下的多个SqlSession是可以共用二级缓存的。二级缓存的缓存写入、清空流程和一级缓存相似,但二级缓存的生命周期是和应用程序的生命周期一致的。为什么?因为Mybatis框架与Spring IOC集成的Mapper对象是单例对象。

另外大家还需要注意下,Mybatis的一级缓存是默认开启的且不能关闭,而二级缓存则需要我们手动开启,我们需要在配置文件中配置cacheEnabled参数。

<configuration>
  <settings>
    <setting name="cacheEnabled" value="true"/>
  </settings>

2.2 Mybatis缓存局限性

面试官:那Mybatis缓存有什么问题吗?

缓存是好,就是问题有点多,目前大厂大都禁止了Mybatis缓存的使用。

南哥总结了下,主要有以下原因。

(1)适用场景少

Mybatis二级缓存更适用于读多写少的业务场景,但是对于细粒度的缓存支持并不友好。举个用烂了的商城例子,每个商品信息的更新是非常频繁的的,而让用户每次都看到的是最新的商品信息又非常重要。

在同一个namespace的Mapper中一般会包含多个商品信息的二级缓存,只要有某一个商品信息更新了,则所有商品缓存都会全部失效。那其实在这个业务场景中,二级缓存的存在已经没有多大必要了,还反而增加了系统复杂性。

(2)数据不一致性问题

如果多个不同namespace的Mapper都共同操作同一个数据库表的情况下,第一个Mapper更新了数据库表会清空它本身的二级缓存,但其他namespace的Mapper是没有感知的,仍然缓存的是旧数据,数据不一致的问题就出现了。

(3)不适用于分布式系统

现在还用单机部署的业务已经不多了,大家都紧跟潮流搭了个分布式、高可用的系统。在分布式系统中,如果每个节点都使用自己的本地缓存,假如现在节点A更新了缓存,但节点B、节点C是不会进行同步更新的,同样产生了数据不一致的问题。

3. Mybatis分页插件

面试官:Mybatis分页插件是怎么实现的?

Mybatis分页的原理其实很简单,没有想象的那么复杂。我们只需要拦截SQL查询语句,再把SQL语句作为子查询,外面包裹一层SELECT * FROM后再加上LIMIT的分页约束语句。

如下SQL示例,确实挺简单的。

SELECT * FROM user
SELECT u.* FROM (SELECT * FROM user) u LIMIT M, N

创作不易,不妨点赞、收藏、关注支持一下,各位的支持就是我创作的最大动力❤️

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
22天前
|
缓存 NoSQL Redis
一天五道Java面试题----第九天(简述MySQL中索引类型对数据库的性能的影响--------->缓存雪崩、缓存穿透、缓存击穿)
这篇文章是关于Java面试中可能会遇到的五个问题,包括MySQL索引类型及其对数据库性能的影响、Redis的RDB和AOF持久化机制、Redis的过期键删除策略、Redis的单线程模型为何高效,以及缓存雪崩、缓存穿透和缓存击穿的概念及其解决方案。
|
22天前
|
前端开发 Java 数据库连接
一天十道Java面试题----第五天(spring的事务传播机制------>mybatis的优缺点)
这篇文章总结了Java面试中的十个问题,包括Spring事务传播机制、Spring事务失效条件、Bean自动装配方式、Spring、Spring MVC和Spring Boot的区别、Spring MVC的工作流程和主要组件、Spring Boot的自动配置原理和Starter概念、嵌入式服务器的使用原因,以及MyBatis的优缺点。
|
2月前
|
canal 缓存 NoSQL
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;先删除缓存还是先修改数据库,双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
|
2月前
|
缓存 算法 Java
关于MyBatis的缓存详解
MyBatis 的缓存机制非常灵活,可以通过简单的配置来满足不同的性能需求。合理地使用缓存可以显著提高应用程序的性能,尤其是在处理大量数据库查询时。然而,开发者需要注意缓存的一致性和并发问题,特别是在使用可读写缓存时。
|
2月前
|
canal 消息中间件 缓存
面试题:如何解决缓存和数据库的一致性问题?
面试题:如何解决缓存和数据库的一致性问题?
48 1
|
28天前
|
缓存 监控 Go
[go 面试] 缓存策略与应对数据库压力的良方
[go 面试] 缓存策略与应对数据库压力的良方
|
2月前
|
SQL Java 数据库连接
Java面试题:简述ORM框架(如Hibernate、MyBatis)的工作原理及其优缺点。
Java面试题:简述ORM框架(如Hibernate、MyBatis)的工作原理及其优缺点。
41 0
|
2月前
|
存储 缓存 算法
Java面试题:给出代码优化的常见策略,如减少对象创建、使用缓存等。
Java面试题:给出代码优化的常见策略,如减少对象创建、使用缓存等。
43 0
|
11天前
|
缓存 NoSQL Redis
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
下一篇
DDNS