面试-mybatis

1. Mybatis的执行流程

  • 读取MyBatis配置文件:mybatis-config.xml加载运行环境和映射文件
  • 构造会话工厂SqlSessionFactory(全局唯一)
  • 会话工厂创建SqlSession对象(包含了执行SQL语句的所有方法)(每一次操作产生一个会话,可以有多个)
  • 操作数据库的接口,Executor执行器,同时负责查询缓存的维护
  • Executor接口的执行方法中有一个MappedStatement对象,封装了映射信息(编写的sql),代表某一次的数据库操作
  • 将java的参数类型转为数据库支持的类型
  • 将数据库的类型转为java相关的类型

image-20240625163223149

2. Mybatis的延迟加载使用及原理

  • 延迟加载的意思是:就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据。
  • Mybatis支持一对一关联对象和一对多关联集合对象的延迟加载
  • 在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false,默认是关闭的

2.1 延迟加载原理

  • 使用CGLIB创建目标对象的代理对象
  • 当调用目标方法时,进入拦截器invoke方法,发现目标方法是null值,执行sql查询
  • 获取数据以后,调用set方法设置属性值(封装),再继续查询目标方法,就有值了

3. Mybatis的一级、二级缓存

  • 本地缓存,基于PerpetualCache,本质是一个HashMap

3.1 一级缓存

  • 作用域是session级别

  • 当Session进行flush或close之后,该Session中的所有Cache就将清空,默认打开一级缓存。

1
2
3
4
5
6
7
8
9
10
11
12
13
//2.获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
//3.执行sql
//3.1获取UserMapper接口的代理对象
UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);

User user = userMapper1.selectById(6);
System.out.println(user);

System.out.println("---------------------");
User user1 = userMapper2.selectById(6);
System.out.println(user1);

只会执行一次SQL

3.2 二级缓存

  • 作用域是namespace和mapper的作用域,不依赖于session,默认是关闭的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//2.获取SqlSession对象,用它来执行sql
SqlSession sqlSession1 = sqlSessionFactory.openSession();

//3.执行sql
//3.1获取UserMapper接口的代理对象
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);

User user1 = userMapper1.selectById(6);
System.out.println(user1);
sqlSession1.close();

SqlSession sqlSession2 = sqlSessionFactory.openSession();

System.out.println("---------------------");
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
User user2 = userMapper2.selectById(6);
System.out.println(user2);

//4.关闭资源
sqlSession2.close();

此时会执行两次SQL查询

3.2.1 打开二级缓存

  • 在mybatis配置文件中开启设置

    1
    2
    3
    <settings>
    <setting name="cacheEnabled" value="true>
    </settings>
  • 在mapper文件中,使用<cache/>标签让当前mapper生效二级缓存

3.3 注意点

  • 数据只要做了非查询(插入、删除、更新),缓存失效
  • 二级缓存需要缓存的数据实现Serializable接口
  • 只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中

面试-mybatis
https://baijianglai.cn/面试-mybatis/e0edc956392f/
作者
Lai Baijiang
发布于
2024年5月10日
许可协议