为什么有,定位在什么,怎么做到的。
如何与其他数据源框架整合
动态sql这一块的体系是需要好好看的,还有 where trim 标签这种
延迟加载是怎么做到的
嵌套映射怎么实现的
高层次的抽象是什么,怎么实现的,单一法则什么的是怎么实现的。
更多的是为什么要这么做,为什么要抽象出这个组件
3.4.x
原生 JDBC 的主要流程:
JDBC Api 介绍:
public class JDBCTest {
@Test
public void testJdbc() {
String url = "jdbc:mysql://localhost:3306/mybatis-learn?user=root&password=root&useUnicode=true&characterEncoding=UTF8&useSSL=false";
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url);
String sql = "SELECT * FROM subject WHERE id = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, 2);
ResultSet rs = stmt.executeQuery();
List<PrimitiveSubject> articles = new ArrayList<>(rs.getRow());
while (rs.next()) {
PrimitiveSubject article = new PrimitiveSubject(
rs.getInt("id"),
rs.getString("name"),
rs.getInt("age"),
rs.getInt("height"),
rs.getInt("weight")
);
articles.add(article);
}
articles.forEach(System.out::println);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
DOM 解析:把整个 XML 文件读取到内存中,构建出一棵 DOM 树,易于编程,但有时 XML 文件过大会消耗大量资源。
XPath:用一种特定的语法来方便获取 DOM 相关节点。
构造者模式,策略模式,责任链
模板方法:类型转换
test 下的代码就很完整了,AutoConstructorTest,SqlSessionTest 都可以
MyBatis 官网简介
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
MyBatis 要解决的问题:
MyBatis 就是对 jdbc 的二次开发,可以称的上是广义上的适配器。
先把核心走一遍,再看各个组件,再走一遍总流程。
接口层: 提供外部接口API,用于开发数据库操作功能。
数据处理层:负责具体的SQL实现,执行数据库SQL操作。
框架支撑层:主要负责将公共功能抽离独立,为数据处理层提供最基础的组件服务,比如:事务管理、缓存管理。
组件一览
SqlSession:顶级接口 API 入口,用于完成所有功能
Executor:MyBatis 执行器,负责 SQL 动态语句生成、查询、维护缓存
StatementHandler:负责 JDBC 与 Statement 交互,包括设置参数、将 JDBC 返回的 ResultSet 结果集转换
XmlConfigBuilderTest#shouldSuccessfullyLoadXMLConfigFile 来测试。
用 xml 的方式加载 mybatis-config。
就是读取到标签,构造成 Configuration,通过反射调用对应字段的 set 方法。
注入 Mapper 的校验:
获取数据源 —— 执行语句 —— 返回值绑定
初始化入口:SqlSessionFactory#build(InputStream inputStream, String environment, Properties properties) 方法
主要做了:加载并解析 mybatis-config.xml 配置文件、映射配置文件以及相关注解等信息。
XMLConfigBuilder,配置解析类,继承的BaseBuilder里面Configuration(解析后的配置),TypeAliasRegistry,TypeHandlerRegistry的都是全局唯一的。
SqlSource 体系
最终会解析成 StaticSqlSource。
DynamicContext:主要用于记录解析动态 SQL 语句之后产生的 SQL 语句片段
一些非核心功能,但又是必要的模块。
MyBatis 对 XML 的解析是用 DOM + XPath 的方式。
org.apache.ibatis.parsing 包下
XPathParser:就是一个解析 XML 的工具类。其实也没啥,就是做了:
GenericTokenParser:就是找到指定占位符,具体解析交给其持有的 Handler
XNode:Node 类和 XPathParser 类的包装类
org.apache.ibatis.type
这里可以说是 ORM 的精髓了,实现了 javaType 与 jdbcType 之间的相互映射关系。JdbcType 是把 java.sql.Types 弄成枚举类,再增加一些其他数据库的定义。
操作了底层的 PreparedStatement CallableStatement ResultSet,是对其包装。
TypeHandler:顶级接口,定义了javaType与jdbcType互相转换的方法。setParameter方法负责将Java Type => JDBC Type,getResult系列方法负责将JDBC Type => Java Type。
设计模式:模板方法
顶级设计
TypeReference:提供了成员变量 rawType,代表泛型 T 真正的类
BaseTypeHandler:对几个方法定义了默认的try catch,具体由子类实现
BaseTypeHandler 的子类一大堆,基本都是直接调用底层的方法set/get,如setInt/getInt。
TypeHandlerRegistry
用于管理 TypeHandler。
TypeHandler 注册:
TypeHandler查找
用户是怎么做到对 TypeHandler 扩展? TypeAliasRegistry 一般用其他连接池中间件。 UnpooledDataSourceFactory 为例,把解析好的 properties 设置到metaDataSource里了。 PooledDataSourceFactory 继承自 UnpooledDataSourceFactory,除了构造 PooledDataSource 以外其他都一样。 一般用 spring 的事务了。 用于将 Mapper 接口与 xml 定义的 SQL 语句关联,便于在编译期就可以发现错误。 MapperRegistry,就是Mapper的注册中心,在启动时,会将Mapper通过addMapper(Class MapperMethod,包含了 SqlCommand和MethodSignature,核心是execute(SqlSession sqlSession, Object[] args) 方法(负责完成数据库各项操作) aMethod(@Param(“M”) int a, @Param(“N”) int b) -> {{0, “M”}, {1, “N”}}
我们也可以添加自定义的 TypeHandler接口实现,添加方式是在 mybatis-config 配置文件中的 typeHandlers 节点下, 加相应的
用于加上各种类的别名,方便我们使用。日志模块
资源加载
数据源连接池
连接数据库,需要有驱动(JDBC已经注册到 DriverManager 里面,直接用即可),还需要用户名、密码、URL。
UnpooledDataSource,重点是getConnection方法的实现,实质上就是拿到 JDBC 注册的驱动,如果没有就自己实例化一个(他的 DriverProxy 更像是装饰者)。
PooledDataSource,核心就是PoolState里的List事务
binding 模块
aMethod(int a, int b) -> {{0, “0”}, {1, “1”}}
aMethod(int a, RowBounds rb, int b) -> {{0, “0”}, {2, “1”}}缓存模块