1. MyBatis使用过程?生命周期?
- 1)创建SqlSessionFactory
可以从配置或者直接编码来创建SqlSessionFactory
1 | String resource = "org/mybatis/example/mybatis-config.xml"; |
- 2)通过SqlSessionFactory创建SqlSession
SqlSession(会话)可以理解为程序和数据库之间的桥梁
1 | SqlSession session = sqlSessionFactory.openSession(); |
- 3)通过sqlsession执行数据库操作
可以通过 SqlSession 实例来直接执行已映射的 SQL 语句:
1 | Blog blog = (Blog)session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101); |
更常用的方式是先获取Mapper(映射),然后再执行SQL语句:
1 | BlogMapper mapper = session.getMapper(BlogMapper.class); |
- 4)调用session.commit()提交事务
如果是更新、删除语句,我们还需要提交一下事务。
- 5)调用session.close()关闭会话

MyBatis生命周期:上面提到了几个MyBatis的组件,一般说的MyBatis生命周期就是这些组件的生命周期
- SqlSessionBuilder:生命周期是方法级的,因为创建完成SqlSeesionFactory后就不需要了
- SqlSeesionFactory:生命周期是贯穿整个应用生命周期的,相当于数据库连接池,并且单例
- SqlSession:非线程安全,不能共享,所以最佳生命周期是一次请求或一个方法
- Mapper:映射器接口的实例是从 SqlSession 中获得的,它的生命周期在sqlsession事务方法之内,一般会控制在方法级。
2. #{}和${}的区别
#{}
匹配的是一个占位符,相当于 JDBC 中的一个?,会对一些敏感字符进行过滤,编译过后会对传递的值加上双引号,因此可以防止 SQL 注入问题。
${}
匹配的是真实传递的值,传递过后,会与 SQL 语句进行字符串拼接。${} 会与其他 SQL 进行字符串拼接,无法防止 SQL 注入问题。
#{}会进行预编译处理,${}是拼接符,字符串替换,不进行预编译处理
#{}可以防止Sql注入
#{}替换在DBMS内,${}替换在DBMS外
Mybatis在处理
#{}
时,#{}
传入参数是以字符串传入,会将SQL中的#{}
替换为?号,调用PreparedStatement的set方法来赋值。
3. MyBatis是否支持延迟加载?原理?
支持,并且Hibernate等也支持,原理如下:
首先Cglib生成目标对象的代理对象,当调用目标方法时进入拦截,比如调用的是A.getB().getName
,拦截器如果发现A.getB()
为空,则会首先保存好需要B对象才能查询的Sql,然后等查询到B后,调用 A.setB(b)
,将其注入A中,此时B不为空,再执行A.getB().getName
。这就是延迟加载的基本原理。
4. 说说Mybatis的一级、二级缓存?
一级缓存
是 SqlSession 级别的缓存。在操作数据库时需要构造 SqlSession 对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的是 SqlSession 之间的缓存数据区(HashMap)是互相不影响,MyBatis默认开启一级缓存。二级缓存
是 Mapper 级别的缓存,多个 SqlSession 去操作同一个 Mapper 的 sql 语句,多个 SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。
5. 能说说MyBatis的工作原理吗?
- 读取 MyBatis 配置文件——mybatis-config.xml 、加载映射文件——映射文件即 SQL 映射文件,文件中配置了操作数据库的 SQL 语句。最后生成一个配置对象。
- 构造会话工厂:通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。
- 创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。
- Executor 执行器:MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。
- StatementHandler:数据库会话器,串联起参数映射的处理和运行结果映射的处理。
- 参数处理:对输入参数的类型进行处理,并预编译。
- 结果处理:对返回结果的类型进行处理,根据对象映射规则,返回相应的对象