配置好后,MyBatis 会根据接口声明的方法信息,通过动态代理机制生成一个Mapper 实例,当调用接口方法时,根据这个方法的方法名和参数类型,确定statement Id,底层还是通过 SQLSession.select/update( “statementId”, parameter) 等来实现对数据库的操作。
数据处理层数据处理层:可以说是MyBatis 的核心,负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等,它主要的目的是根据调用的请求完成一次数据库操作。
从大的方面上讲,它要完成两个功能:
- 通过传入参数构建动态sql语句
- SQL语句的执行以及封装查询结果集
动态语句生成能够说是MyBatis框架很是优雅的一个设计,MyBatis 经过传入的参数值,使用 Ognl 来动态地构造SQL语句,使得MyBatis 有很强的灵活性和扩展性。
参数映射指的是对于Java 数据类型和jdbc数据类型之间的转换,这里有包括两个过程:
- 查询阶段
- 查询结果集转换阶段
查询阶段要将java类型的数据,转换成jdbc类型的数据,经过 preparedStatement.setXXX() 来设值;
另外一个就是对resultset查询结果集的jdbcType 数据转换成java 数据类型。
2. SQL语句的执行以及封装查询结果集动态SQL语句生成以后,MyBatis 将执行SQL语句,并将可能返回的结果集转换成List<E> 列表。
MyBatis 在对结果集的处理中,支持结果集关系一对多和多对一的转换,而且有两种支持方式,一种为嵌套查询语句的查询,还有一种是嵌套结果集的查询。
基础支撑层基础支撑层是整个MyBatis框架的地基,负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件,为上层的数据处理层提供最基础的支撑。
1.缓存机制数据库是实践生成中非常核心的存储,很多业务数据都会落地到数据库,所以数据库性能的优劣直接影响了上层业务系统的优劣。
我们很多线上业务都是读多写少的场景,在数据库遇到瓶颈时,缓存是最有效、最常用的手段之一,正确使用缓存可以将一部分数据库请求拦截在缓存这一层,这就能够减少一部分数据库的压力,提高系统性能。
除了使用 Redis、Memcached 等外置的第三方缓存以外,持久化框架一般也会自带内置的缓存,例如,MyBatis 就提供了一级缓存和二级缓存,具体实现位于基础支撑层的缓存模块中。
2.反射工具该模块对 Java 原生的反射进行了良好的封装,提供了更加简洁易用的 API ,方便上层使调用,并且对反射操作进行了一系列优化,例如缓存了类的元数据,提高了反射操作的性能。
3.类型转换类型转换模块提供了两个主要功能,一个功能是别名机制,MyBatis 为了简化配置文件提供了别名机制。
另一个功能是实现 JDBC 类型与 Java 类型之间的转换,该功能在为 SQL 语句绑定实参以及映射查询结果集时都会涉及。
4.日志提供详细的日志输出信息,并且能够集成多种日志框架,其日志模块的一个主要功能就是集成第三方日志框架。
5.资源加载资源加载模块主要是对类加载器进行封装,确定类加载器的使用顺序,并提供了加载类文件以及其他资源文件的功能。
6.解析器解析器模块主要提供两个功能,一个功能是对 XPath 进行封装,为 MyBatis 初始化时解析 mybatis-config.xml 配置文件以及映射配置文件提供支持。
另一个功能是为处理动态 SQL 语句中的占位符提供支持。
7.事务管理持久层框架一般都会提供一套事务管理机制实现数据库的事务控制,MyBatis 对数据库中的事务进行了一层简单的抽象,提供了简单易用的事务接口和实现。
一般情况下,Java 项目都会集成 Spring,并由 Spring 框架管理事务。
8.Binding在调用 SqlSession 相应方法执行数据库操作时,需要指定映射文件中定义的 SQL 节点,如果出现拼写错误,我们只能在运行时才能发现相应的异常。为了尽早发现这种错误,MyBatis 通过 Binding 模块将用户自定义的 Mapper 接口与映射配置文件关联起来,系统可以通过调用自定义 Mapper 接口中的方法执行相应的SQL 语句完成数据库操作,从而避免上述问题。
需要注意的是,开发人员无须编写自定义 Mapper 接口的实现,MyBatis 会自动为其创建动态代理对象。
9.数据源对于 ORM 框架而言,数据源的组织是一个非常重要的一部分,这直接影响到框架的性能问题。
数据库连接是一项有限的昂贵资源,一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完都关闭连接,这样造成系统的性能低下。
数据库连接池的解决方案是在应用程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由应用程序动态地对池中的连接进行申请、使用和释放。
打开Mybatis源码找到datasource包下就可以看到连接池的实现,如下图所示: