-
JDBC 查询操作步骤
- 注册数据库驱动类,明确指定数据库 URL 地址、数据库用户名、密码等连接信息。
- 通过 DriverManager 打开数据库连接
- 通过数据库连接创建 Statement 对象。
- 通过 Statement 对象执行 SQL 语句,得到 ResultSet 对象。
- 通过 ResultSet 读取数据,并将数据转换成 JavaBean 对象。
- 关闭 ResultSet、Statement 对象以及数据库连接,释放相关资源。
- Hibernate
- JPA(Java Persistence API)
- Spring JDBC
- MyBatis
-
基础支持层
-
数据源模块
- 连接池
- 监控等
-
事务管理模块
- 多半与 Spring 集成,由 Spring 进行管理
-
缓存模块
- 一级缓存
- 二级缓存
-
Binding 模块
- 将用户自定义的 Mapper 接口与映射配置文件关联起来,系统可以通过调用自定义 Mapper 接口中的方法执行相应的 SQL 语句完成数据库操作,从而避免映射文件中定义的 SQL 节点拼写错误等问题。
- 无须编写自定义 Mapper 接口的实现,MyBatis 会自动为其创建动态代理对象。
-
反射模块
- 对 Java 原生的反射进行了良好的封装,提供了更加简洁易用的 API,方便上层使调用,并且对反射操作进行了一系列优化,例如缓存了类的元数据,提高了反射操作的性能。
-
类型转换
- 别名
- 实现 JDBC 类型与 Java 类型之间的转换
-
日志模块
- 提供详细的日志输出信息,还能够集成多种日志框架。
-
资源加载
- 对类加载器进行封装,确定类加载器的使用顺序,并提供了加载类文件以及其他资源文件的功能。
-
解析器模块
- 对 XPath 进行封装,为 MyBatis 初始化时解析 mybatis-config.xml 配置文件以及映射配置文件提供支持
- 处理动态 SQL 语句中的占位符提供支持
-
-
核心处理层
-
配置解析
- 在 MyBatis 初始化过程中,会加载 mybatis-config.xml 配置文件、映射配置文件以及 Mapper 接口中的注解信息,解析后的配置信息会形成相应的对象并保存到 Configuration 对象中。 待 MyBatis 初始化之后,开发人员可以通过初始化得到 SqlSessionFactory 创建的 SqlSession 对象并完成数据库操作。
-
参数映射
-
scripting 模块
- 根据用户传入的实参,解析映射文件中定义的动态 SQL 节点,并形成数据库可执行的 SQL 语句。然后处理 SQL 语句中的占位符,绑定用户传入的实参。
-
-
SQL 解析
- 动态 SQL 语句,提供多种动态 SQL 语句对应的节点,、、等
-
SQL 执行
-
Executor
- 主要负责维护一级缓存和二级缓存,并提供事务管理的相关操作,会将数据库相关操作委托给 StatementHandler 完成
-
StatementHandler
- 首先通过 ParameterHandler 完成 SQL 语句的实参绑定,然后通过 java.sql.Statement 对象执行 SQL 语句并得到结果集
-
ParameterHandler
-
ResultHandler
- 完成结果集的映射,得到结果对象并返回
-
-
结果集映射
-
插件
-
-
接口层
- SqlSession
-
适配器模式
http://www.glorze.com/699.html
- 参考当前项目的《设计模式.xmind》
-
日志适配器
-
Log
- 定义了日志模块的功能
-
LogFactory
- 负责创建对应的日志组件适配器
-
总体逻辑
- LogFactory 类加载时会执行其静态代码块,其逻辑是按序加载并实例化对应日志组件的适配器,然后使用 LogFactory.logConstructor 这个静态字段,记录当前使用的第三方日志组件的适配器。
-
-
代理模式与 JDK 动态代理
http://www.glorze.com/1713.html
http://www.glorze.com/1193.html
-
代理模式参考当前项目的《设计模式.xmind》
-
JDK 动态代理的总体逻辑
- JDK 动态代理的实现原理是动态创建代理类并通过指定类加载器加载,然后在创建代理对象时将 InvokerHandler 对象作为构造参数传入。
- 当调用代理对象是,会调用 InvokerHandler.invoke() 方法,并最终调用真正业务对象的相应方法。
-
-
JDBC 调试
-
工厂方法模式
-
MyBatis 使用不同的 DataSourceFactory 接口实现创建不同类型的 DataSource
- 连接池数据资源
- 非连接池数据资源
-
-
DataSourceFactory(抽象工厂)
- PooledDataSourceFactory
- UnpooledDataSourceFactory
-
DataSource(抽象产品)
- PooledDataSource
- UnpooledDataSource
-
装饰器模式
-
Cache 接口及其实现
-
方法声明
-
getId
- 缓存对象的 ID
-
putObject
- 向缓存中添加数据,一般情况下,key 是 CacheKey,value 是查询结果
-
getObject
- 根据指定的 key,在缓存中查找对应的结果对象
-
removeObject
- 删除 key 对应的缓存项
-
clear
- 清空缓存
-
getSize
- 缓存项的个数,该方法不会被 MyBatis 核心代码使用,所以可提供空实现
-
getReadWriteLock
- 获取读写锁,该方法不会被 MyBatis 核心代码使用,所以可提供空实现
-
-
PerpetualCache
- Cache 接口的基本实现
- 底层使用 HashMap 记录缓存项,也是通过该 hashMap 对象的方法实现的 Cache 接口中定义的相应方法
-
装饰类
-
BlockingCache
- 阻塞版本的缓存装饰器,它会保证只有一个线程到数据库中查找指定 key 对应的数据
-
FifoCache
- 在很多场景中,为了控制缓存的大小,系统需要按照一定的规则清理缓存。
- FifoCache 是先入先出的装饰器,当向缓存添加数据时,如果缓存项的个数己经达到上限,则会将缓存中最老(即最早进入缓存)的缓存项删除。
-
LruCache
- 按照近期最少使用算法进行缓存清理的装饰器,在需要清理缓存时,它会清除最近最少使用的缓存项。
- 底层使用 LinkedHashMap
-
SoftCache & WeakCache
- 在 SoftCache 中,最近使用的一部分缓存项不会被 GC 回收,这就是通过将其 value 添加到 hardLinksToAvoidGarbageCollection 集合中实现的(即有强引用指向其 value)
- hardLinksToAvoidGarbageCollection 集合是 LinkedList 类型
- WeakCache 的实现与 SoftCache 基本类似,唯一的区别在于其中使用 WeakEntry 封装真正的 value 对象
-
ScheduledCache
- 周期性清理缓存的装饰器
- clearInterval 属性记录两次缓存清理之间的时间间隔,默认是一小时
- lastClear 属性记录最近一次清理的时间戳
-
LoggingCache
- 在 Cache 的基础上提供了日志功能
- requests 属性记录了缓存的缓存的访问次数
- hits 属性记录了缓存的命中次数
-
SynchronizedCache
- 通过在每个方法上添加 synchronized 关键字,为 Cache 添加了同步功能
-
SerializedCache
- 提供将 value 对象序列化的功能
- 在添加缓存项时,会将 value 对应的 Java 对象进行序列化,并将序列化后的 byte 数组作为 value 存入缓存
- 在获取缓存项时,会将缓存项中的 byte 数组反序列化成 Java 对象。
- 使用其他装饰器实现进行装饰之后,每次从缓存中获取同一 key 对应的对象时,得到的都是同一对象,任意一个线程修改该对象都会影响到其他线程以及缓存中的对象;
-
CacheKey
-
表示缓存项的 key
- 在 Cache 中唯一确定一个缓存项需要使用缓存项的 key, Mybatis 中因为涉及动态 SOL 等多方面因素,其缓存项的 key 不能仅仅通过一个 String 表示,所以 Mybatis 提供了 CacheKey 类来表示缓存项的 key,在一个 CacheKey 对象中可以封装多个影响缓存项的因素。
- CacheKey 中可以添加多个对象,由这些对象共同确定两个 CacheKey 对象是否相同
-
重要属性
-
multiplier
- 参与计算 hashcode,默认值是 37
-
hashcode
- CacheKey 对象的 hashcode,起始值是 17
-
checksum
- 校验和
-
count
- updateList 集合的个数
-
updateList
- 由该集合中的所有对象共同决定两个 CacheKey 是否相同
-
-
-
MyBatis 中的配置文件
- mybatis-config.xml
- 映射配置文件
-
初始化主要工作
- 加载并解析 mybatis-config.xml 配置文件
- 映射配置文件以及相关的注解信息
-
建造者模式
-
BaseBuilder(建造者接口)
-
Configuration configuration
- Configuration 是 MyBatis 初始化过程的核心对象,MyBatis 中几乎全部的配置信息会保存到 Configuration 对象中
- Configuration 对象是在 MyBatis 初始化过程中创建且是全局唯一的,也叫「All-In-One」 配置对象
-
TypeAliasRegistry typeAliasRegistry
- 在 mybatis-config.xml 配置文件中可以使用 标签定义别名,这些定义的别名都会记录在该 TypeAliasRegistry 对象中
-
TypeHandlerRegistry typeHandlerRegistry
- 在 mybatis-config.xml 在配置文件中可以使用 标签添加自定义 TypeHandler 处理器,完成指定数据库类型与 Java 类型的转换这些 TypeHandler 都会记录在 TypeHandlerRegistry 中。
-
-
XMLConfigBuilder
-
BaseBuilder 的一个具体建造者,主要负责解析 mybatis-config.xml 配置文件
-
主要变量
-
boolean parsed
- 标识是否已经解析过 mybatis-config.xml 配置文件
-
XPathParser parser
- 用于解析 mybatis-config.xml 配置文件的 XPathParser 对象
-
String environment
- 标识 配置的名称,默认读取 标签的 default 属性
-
ReflectorFactory localReflectorFactory
- ReflectorFactory 负责创建和缓存 Reflector 对象
-
-
解析节点
- properties 节点
- settings 节点
- typeAliases、typeHandlers 节点
- plugins 节点
- objectFactory 节点
- environments 节点
- databaseIdProvider 节点
- mappers 节点
-
-
XMLMapperBuilder
- 负责解析映射配置文件,也是继承 BaseBuilder 抽象类,具体建造者的角色
- 解析 节点
- 解析 节点
- 解析 节点
- 解析 节点
- 解析 节点
-
XMLStatementBuilder
- 解析主要用于定义 SQL 语句的 节点
- 解析 节点
- 解析 节点
- 解析 SQL 节点
-
绑定 Mapper 接口
- 每个映射配置文件的命名空间可以绑定一个 Mapper 接口,并且注册到 mapperRegistry 中。
-
处理 incomplete*集合
- XMLMapperBuilder.configurationElement 方法解析映射配置文件时,是按照从文件头到文件尾的顺序解析的,但是有时候在解析一个节点时,会引用定义在该节点之后的、还未解析的节点,这就会导致解析失败并抛出 IncompleteElementException。
- 根据抛出异常的节点不同,MyBatis 会创建不同的 Resolver 对象,并添加到 Configuration 的不同 incomplete 集合中。
而 SerializedCache 每次从缓存中获取数据时,都会通过反序列化得到一个全新的对象。
-
-