本文已参与「新人创作礼」活动,一起开启掘金创作之路。
1. 说说Mybatis的三层
MyBatis主要分为三层:接口层,数据处理层与基础层。
接口层是通过提供的API作为数据库进行增/删/改/查,都是MyBatis的API。提供主要用的两个接口:
- SqlSessionFactory:它是通过configration构造的接口对象,然后通过该接口对象构造SqlSession对象。
- SqlSession:作用是提供加载映射文件中的mapperstatement对象。并提供增删改查的方法
数据处理层是SQL预处理、SQL执行、结果映射。
- SQL预处理:是对代码里的变量进行绑定,以及动态SQL生成
- SQL执行:是把生成好的SQL,通过JDBC驱动,传到对应的DB里执行,而且要负责网络通信的部分
- 结果映射:是把数据库返回的结果从关系型数据转换成Java对象数据。
基础层包括日志、事务管理、缓存、连接池、动态代理、配置解析。
- 日志:是做框架里面的日志输出以及SQL语句输出
- 事务管理:是对 JDBC事务、数据库事物做管理;
- 缓存:能够把结果集缓存在JVM的内存。优点是比较快,缺点是会占用堆内存。实际上一般使用Redis这样的中间件来做分布式缓存
- 连接池:能够加速查询,提高性能
- 动态代理:在用MyBatis编程时,核心是通过接口执行数据库查询。而Mapper接口本身是没有实现的,通过注解或者XML配置SQL语句,动态代理会在运行时生成代理,当调用Mapper接口时,转换成实际的SQL语句
- 配置解析:因为MyBatis里面有存在大量配置,需要配置新模块,读取XML配置,并把它映射为配置属性。
2. Mybatis的映射过程
加载sql语句,获取表中数据然后将数据返回给结果集,从结果集中获取数据(取出每个字段),通过构造器给对象赋值
3. Mybatis的事务管理类型
- 原生JDBC,对应的事务相关操作都由mybatis内置的
JdbcTransaction来完成, - MANAGED,对事务的管理是一个空实现,将事务管理交给外部容器,例如交给Spring来实现,
无论是哪种方式,都是使用jdk利用数据库的Connection来提供管理事务的能力,都是一层一层的封装进行委派最终由Connection的具体数据库驱动来进行实现的
4. Mybatis的数据源
POOLED:采用传统的javax.sql.DataSource规范中的连接池,对连接进行了缓存
UNPOOLED:采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想
JNDI:采用服务器提供的JNDI技术实现,来获取DataSource对象,通过JNDI上下文中取值
5. 连接池思想
创建一个Conncection代价是巨大的,因为创建了一个连接,在底层就与数据库建立了通信连接,
- TCP 建立连接 三次握手
- MySql 认证的 三次握手
- SQL 的执行
- MySql 的关闭
- TCP 的 四次握手 关闭连接
网络IO较多,数据库的负载较高、应用频繁的创建连接和关闭连接,导致临时对象较多,GC频繁,所以说是非常消耗资源的操作,从用户的角度来讲,导致响应时间较长以及QPS较低 ,而为数据库建立一个“连接池”,预先创建一定数量的连接,当需要连接时,只需从中取出一个,使用完毕之后再放回,避免了连接随意建立和关闭造成的系统开销。
6. 连接池原理
服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接。
客户端程序需要连接时,池驱动程序会返回一个未使用的池连接并将其表记为忙。
如果当前没有空闲连接,池驱动程序就新建一定数量的连接,新建连接的数量由具体的配置参数决定。
当使用的池连接调用完成后,池驱动程序将此连接表记为空闲,其他调用就可以使用这个连接。
7. Mybatis是怎么将mapper与xml联系起来的
当加载映射文件时,会将每个sql标签加载成不同的MapperStatement对象。MapperStatement对象的id = namespace(接口的全限定名) + mapper的方法名,在MyBatis中,每一个< select>、< insert>、< update>、< delete>标签都会被解析为一个MapperStatement对象