Spring Boot+MyBatis+Druid的使用是基础,在项目中贯穿。
1. MyBatis是什么
答:MyBatis是一个半ORM的框架,内部封装了JDBC,通过xml文件或注解配置信息。通过Java对象和statement的SQL参数映射执行SQL语句生成Java对象返回。
1.1 MyBatis和JDBC的区别
答:总结为:
- MyBatis代码量少,开发速度快,移植性好,缺点是sql语句自己写;
- JDBC更灵活但存在硬编码和数据库连接开启关闭频繁。
2. 核心组件
答:MyBatis的核心组件包括SqlSessionFactoryBuilder,SqlSessionFactory,SqlSession和Mapper。
2.1 SqlSessionFactoryBuilder
SqlSessionFactoryBuilder是一个构造器,通过配置文件或者java代码获得资源构造工厂类。可以构造多个工厂。生命周期在方法内部,用完就回收。
SqlSessionFactory factory = SqlSessionFactoryBuilder.build(inputStream);
2.2 SqlSessionFactory
SqlSessionFactory的作用就是创建SqlSession,一个会话。用单例模式创建SqlSession。生命周期贯穿整个MyBatis。
SqlSession sqlSession = SqlSessionFactory.openSession();
2.3 SqlSession
SqlSession就是一个会话,作用是发送SQL语句和获取Mapper接口。生命周期是请求数据库处理事务的过程中。注意每次SqlSession使用完后需要关闭,减少资源消耗。
2.4 Mapper
Mapper映射器,给出对应的SQL和映射规则。作用是发送SQL去执行并返回结果。
XXMapper xxMapper = sqlSession.getMapper(XXMapper.class);
3. 动态SQL
答:在xml写mapper时能用if、where、foreach等标签。原理是根据表达式的值完成逻辑判断并动态拼接SQL语句。
总共提供了9种标签:
- if:单条件分支
- choose、when、otherwise:多条件分支
- foreach:循环遍历
- trim、where、set:辅助元素,实现SQL拼接
- bind:模糊查询
我们还能把动态SQL提取出来,用id标志。
4. Dao接口的工作原理
答:Dao接口就是Mapper接口。
开发规范:
- 接口的全路径名要与映射文件中的namespace相同;
- 方法名要与映射文件中的statement的id相同;
- 方法参数为传递给SQL的参数;
- 返回值要与映射文件中的resultType或resultMap一致。
工作原理:JDK的动态代理,为Mapper接口生成代理对象,代理对象会拦截接口方法,执行MapperStatement(每个标签都会解析为一个MapperStatement对象)对应的SQL,将结果返回。
4.1 Dao的接口方法可以重载吗?
答:不能重载,因为接口内部使用 全限定名+方法名 保存和查找。
4.2 不同的xml文件中id能重复吗?
答:xml文件如果配置了namespace,就可以重复;没有配置,不能重复。
4.3 接口绑定实现方式
答:接口绑定就是在MyBatis中定义接口,然后把接口里的方法和SQL语句绑定。
- 通过注解绑定。在方法上添加@Select、@Update注解 + SQL语句;
- 通过xml里写SQL绑定。注意mapper的开发规范。
5. MyBatis中#和$的区别
答:能用#就用# 。区别在:
- #符号相当于占位符,$符号相当于拼接SQL串;
- #符号将传入的数据都当成一个字符串,$符号将传入的数据直接原样输出;
- #符号有预编译,能防止SQL注入,$符号是直译,不能防止注入。
6. MyBatis的缓存机制
答:MyBatis分为一级和二级缓存。
- 一级缓存:SqlSession级别的缓存,基于HashMap实现,默认开启;
- 二级缓存:Mapper级别的缓存,多个SqlSession共用,基于HashMap实现。默认不开启,开启后,一级缓存失效。
7.延迟加载
又名懒加载,即先查询主表信息,若用到从表数据,再去查询从表信息,不用到,就不查询。
操作步骤:
- 开启延迟加载
在全局配置文件中,添加setting。
<settings>
//打开延迟加载的开关,默认为true
<setting name="lazyLoadingEnabled" value="true"/>
//积极的懒加载,默认是true,设置为false时,懒加载生效
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
- 编写主表的查询映射
比如orders,一对一查询,user。
在association中以select属性选取从表查询。
- 正常编写从表的查询映射