# JDBC
需要手动引入 Mysql 的 jar 包
1 | public class JDBCDemo { |
- 为什么要有 ORM 框架
- 驱动 uri、数据库地址、账号密码,硬编码,不灵活
- 重复的建立连接
- 处理结果集麻烦
# 自定义
# 创建两个工程
- IPersistence、IPersistence_Test
# IPersistence_Test 使用端
# IPersistence 自定义框架
# 根据配置文件的路径,将配置文件加载成字节输入流,存储在内存中
1 | Resources.getResourceAsStream(String path) |
- 获得 sqlSession 对象
sqlSession 通过 sqlSessionFatory.open 获得
sqlSessionFatory 通过 sqlSessionFatoryBuilder.build (configuration) 获得
build 需要获取数据库信息
- 创建 SqlSessionFactoryBuilder
- 通过 SqlSessionFatoryBuilder.build () 获得 SqlSessionFatory
- 通过 DefaultSqlSessionFactory.open () 获得 SqlSession
- 创建 DefaultSqlSession 实现基础方法 selectAll,selectList
- 执行 JDBC 逻辑
创建 Executor、Executor 实现类,执行 CURD
- 处理返回结果
通过反射或内省 + SQLID 上的 resultType 全路径,处理返参
- 问题 1:数据库类型与实体类型不一致
1
Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498)
- 问题 2:数据库版本与驱动版本不一致
无法获取数据库连接,报错信息和获取连接方法有关
使用 C3P0 连接池是报错:
1 | java.sql.SQLException: Connections could not be acquired from the underlying database! |
使用 DriverManager 直接连接时:
1 | Client does not support authentication protocol requested by server; consider upgrading MySQL client |
- 持久层实现
通过 mapper 接口,数据库的交互
SqlSession 中创建一个 getMapper 方法,获取 mapper 的代理类,执行被代理类的方法
# Mybatis
# 概念
基于 ORM 的 半自动
轻量级持久层框架。
# 缓存
底层数据结构: 就是一个 HashMap。
先去缓存中查,然后到数据库中,如果缓存中有,就直接返回,不再去数据库查询。
# 一级缓存 - SqlSession 级别
是否启用: 默认开启
cacheKey: org.apache.ibatis.executor.BaseExecutor#createCacheKey
增删改操作时,会刷新缓存(全部缓存)
# 二级缓存 - NameSpace 级别
是否启用: 默认关闭,需要手动开启
[I] 二级缓存是在 SqlSession 事务提交时写入的
[!] 二级缓存在分布式的情况下,可能有问题。
1 |
|
结论: 节省了数据库的交互
Q:
1 |
|
# 插件
- [I] 需要在 SqlMapConfig.xml 中启用
1 | <plugins> |
# 分页插件
拦截器实现
[*]
com.github.pagehelper.PageHelper
[*] 入口:
com.github.pagehelper.SqlUtil#_processPage
[*] 增加 COUNTSQL:
com.github.pagehelper.MSUtils#processCountMappedStatement(MappedStatement ms, SqlSource sqlSource, Object[] args)
countSql 返回结果大于 0 时,执行分页,将总数设置到 page 对象中
替换参数
com.github.pagehelper.MSUtils#processPageMappedStatement(MappedStatement ms, SqlSource sqlSource, Page page, Object[] args)
创建新的 mapperStatement,执行分页 SQL
设置分页参数:
com.github.pagehelper.MSUtils#setPageParameter
# 通用 Mapper
# 架构原理
# 架构设计
# 接口
- 通过 sqlSession.method (statementId) 或者 Mapper 代理类调用方法,执行主句的增删改查。
- 调用接口修改配置信息等。
# 数据处理
- 请求参数处理 (@Param):ParameterHandler
- SQL 解析 (处理占位符、Mapper 标签):SqlSource
- SQL 执行 (JDBC):Executor
- 返回结果处理 (类型转换等):ResultSetHandler
# 框架支撑
- 事务管理
- 连接池管理
- 缓存机制
# 主要构件
SqlSession:session 表示与数据库的连接
Executor:执行器
StatementHandler:
ParameterHandler:
BoundSql:
ResultSetHander:
TypeHandler:数据库类型与 JavaBean 类型的转换
MappedStatement:
SqlSource:
# 总体流程
- SqlSessionFactoryBuilder 获取 SqlSessionFactory
- SqlSessionFactory.openSession 获取 SqlSession 对象
- 通过 getMapper 获取 Mapper 代理对象
- 执行代理 Mapper 的方法
- => Executor Mybatis 的执行器
- => StatementHandler 与 JDBC Statement 的交互
- => ParameterHandler 处理方法中携带的参数,拼接到 Sql 中
- => 执行 JDBC 流程(加载驱动、建立连接、定义 Sql、获取预处理对象、处理参数、执行、处理返回结果)
- => 处理 Java 类型和数据库类型映射