一, 前言
撸完 Spring 框架, 我们接着下一个征程, Mybatis. 相对 Spring 而言, Mybatis 就显得短小精悍. 在本系列源码开始之前, 我们先来一起了解下 Mybatis 的相关知识点.
二, 什么是 MyBatis ?
MyBatis 是一款优秀的持久层框架, 它支持定制化 SQL, 存储过程以及高级映射. MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集. MyBatis 可以使用简单的 xml 或注解来配置和映射原生信息, 将接口和 Java 的 POJOs(Plain Old Java Objects, 普通的 Java 对象) 映射成数据库中的记录.
三, 架构
1, 接口层
接口层主要定义的是与数据库进行交互的方式. 在 Mybatis 中, 交互分为两种方式.
Mybatis 提供的 API
使用 Mybatis 提供的 API 进行操作, 通过获取 SqlSession 对象, 然后根据 Statement Id 和参数来操作数据库.
- String statement = "com.viewscenes.netsupervisor.dao.UserMapper.getUserList";
- List<User> result = sqlsession.selectList(statement);
使用 Mapper 接口
事实上这个才是经常使用的方式, 面向接口编程嘛. 每一个 Mapper 接口中的方法对应着 mapper.xml 文件中的一个 select/insert/update/delete 节点. 节点中的 ID 就是接口中的方法名, 在使用的时候直接调用接口方法即可. 不过, 值得注意的是, 它最终执行的还是 sqlSession.select(),sqlSession.delete().
2, 数据处理层
这是 Mybatis 的核心. 它负责参数映射和动态 SQL 生成, 生成之后 Mybatis 执行 SQL 语句, 并将返回的结果映射成自定义的类型. 关于参数映射和结果集转换, 主要是靠 typeHandlers. 为便于理解, 我们大概来看几个类型处理器.
类型处理器 | Java 类型 | JDBC 类型 |
---|---|---|
StringTypeHandler | java.lang.String | CHAR, VARCHAR |
DateTypeHandler | java.util.Date | TIMESTAMP |
BooleanTypeHandler | java.lang.Boolean, boolean | 数据库兼容的 BOOLEAN |
IntegerTypeHandler | java.lang.Integer, int | 数据库兼容的 NUMERIC 或 INTEGER |
3, 框架支撑层
事务管理
对于 ORM 框架而言, 事务管理是必不可少的一部分. 不过, 一般情况下, Mybatis 都是和 Spring 搭配使用的, 更多的是用 Spring 来接管事务管理.
连接池
我们不能每次在执行 SQL 的时候才去创建数据库的连接. 因为创建连接是一个相对比较耗时的操作, 通常做法是用一个列表保存提前创建好的 N 个连接, 用到的时候去拿, 用完再还回去. 关于数据库连接池, 业界有很多开源实现. 比如 C3P0,DBCP,Tomcat Jdbc Pool,BoneCP,Druid 等.
缓存
为了提高数据利用率和减小服务器和数据库的压力, Mybatis 会对于一些查询提供会话级别的数据缓存, 会将对某一次查询, 放置到 SqlSession 中, 在允许的时间间隔内, 对于完全相同的查询, MyBatis 会直接将缓存结果返回给用户, 而不用再到数据库中查找.
一级缓存是 SqlSession 级别的缓存, 在同一个 sqlSession 中两次执行相同的 sql 语句, 第一次执行完毕会将数据库中查询的数据写到缓存 (内存), 第二次会从缓存中获取数据将不再从数据库查询, 从而提高查询效率, Mybtais 默认开启一级缓存.
二级缓存是 mapper 级别的缓存, 多个 SqlSession 去操作同一个 Mapper 的 sql 语句, 多个 SqlSession 去操作数据库得到数据会存在二级缓存区域, 多个 SqlSession 可以共用二级缓存, 二级缓存是跨 SqlSession 的. 要开启二级缓存, 需要在你的 SQL 映射文件中添加一行:. 它会将所有的 select 语句缓存, 在执行 insert,update 和 delete 语句时会刷新缓存, 缓存根据 LRU 算法来回收.
4,SQL 配置方式
大部分时候我们都是通过 xml 方式来配置 SQL, 不过 Mybatis 也支持通过注解来配置, 就像下面这样.
- @Select({"<script>", "select * from user"
- "</script>"})
- List<ConsultContent> getUserList();
不过, 不推荐这种方式来搞, 除非你想挖坑.... 想想吧, 一个复杂的 SQL, 几十行上百行, 写时一时爽, 维护满面泪.
5, 引导层
引导层是配置和启动 MyBatis 配置信息的方式. MyBatis 提供两种方式来引导 MyBatis : 基于 xml 配置文件的方式和基于 Java API 的方式.
四, 主要构件
SqlSession 作为 MyBatis 工作的主要顶层 API, 表示和数据库交互的会话, 完成必要数据库增删改查功能.
Executor MyBatis 执行器, 是 MyBatis 调度的核心, 负责 SQL 语句的生成和查询缓存的维护.
StatementHandler 封装了 JDBC Statement 操作, 负责对 JDBC statement 的操作, 如设置参数, 将 Statement 结果集转换成 List 集合.
ParameterHandler 负责对用户传递的参数转换成 JDBC Statement 所需要的参数.
ResultSetHandler 负责将 JDBC 返回的 ResultSet 结果集对象转换成 List 类型的集合.
TypeHandler 负责 java 数据类型和 jdbc 数据类型之间的映射和转换.
MappedStatement MappedStatement 维护了一条 < select|update|delete|insert > 节点的封装.
SqlSource 负责根据用户传递的 parameterObject, 动态地生成 SQL 语句, 将信息封装到 BoundSql 对象中, 并返回.
BoundSql 表示动态生成的 SQL 语句以及相应的参数信息.
Configuration MyBatis 所有的配置信息都维持在 Configuration 对象之中.
五, 版本
本系列采用的数据库为 MySQL,Mybatis 版本为 3.4.6. 以下是 pom 文件坐标.
- <dependency>
- <groupId>org.mybatis</groupId>
- <artifactId>mybatis</artifactId>
- <version>3.4.6</version>
- </dependency>
- <dependency>
- <groupId>org.mybatis</groupId>
- <artifactId>mybatis-spring</artifactId>
- <version>1.3.2</version>
- </dependency>
- <dependency>
- <groupId>MySQL</groupId>
- <artifactId>MySQL-connector-java</artifactId>
- <version>6.0.6</version>
- </dependency>
- <dependency>
- <groupId>com.mchange</groupId>
- <artifactId>c3p0</artifactId>
- <version>0.9.5.2</version>
- </dependency>
来源: https://juejin.im/post/5c84b3c45188257e453c5d37