本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看 活动链接
总文档 :文章目录
Github : github.com/black-ant
一 . 前言
JPA 使用过程中 , 经常会出现解析的异常 ,通过以下流程 , 有利于找到对应的节点
1.1 前置知识点
EntityManager
EntityManager 实例与持久性上下文关联。
持久性上下文是一组实体实例,其中对于任何持久性实体标识,都存在唯一的实体实例。在持久化上下文中,管理实体实例及其生命周期。EntityManager API 用于创建和删除持久性实体实例,根据实体的主键查找实体,以及查询实体。
persistent 简介
persistent 是持久化上下文 , 用于将事务持久化
持久性上下文处理一组实体,这些实体包含要在某个持久性存储中持久化的数据(例如数据库)。特别是,上下文知道一个实体在上下文和底层持久性存储方面可能具有的不同状态(例如托管、分离)。
persistent 功能
- 持久性上下文通常通过 EntityManager 访问
- 每个EntityManager实例都与一个持久化上下文相关联。
- 在持久化上下文中,管理实体实例及其生命周期。
- 持久化上下文定义了一个作用域,特定实体实例在这个作用域下被创建、持久化和删除。
- 持久化上下文类似于包含一组持久化实体的缓存,因此一旦事务完成,所有持久化对象都将从EntityManager的持久化上下文中分离出来,不再进行管理。
persistent 的分类
- Transaction-scoped persistence context
- Extended-scoped persistence context
二 . 逻辑流程
2.1 SQL 解析主流程
主流程可以分为几个部分 :
Execute Action 入口流程
1 | java复制代码// Step 1 : ExecutableList 处理 |
M54_01M54_02M55_02M54_03M56_01statement 请求流程statement 创建返回 statement对 statement 再次处理注册JDBC语句M54_01M54_02M55_02M54_03M56_01
Insert 操作准备流程 :
注意其中的核心逻辑 M54_01
其中主要是 Statement 的处理 , 请求和创建 :
- AbstractEntityPersister # insert -> M53_01
- AbstractEntityPersister # insert -> M53_02
- StatementPreparerImpl # prepareStatement -> M54_01
- StatementPreparerImpl # buildPreparedStatementPreparationTemplate -> M54_02
- HikariProxyConnection # prepareStatement
- ProxyConnection # prepareStatement
- ConnectionImpl # prepareStatement -> M55_01
- ConnectionImpl # clientPrepareStatement -> M55_02
postProcess 处理流程 , statement 注册
- StatementPreparerImpl # postProcess -> M54_03 (M54_01 -> M54_03 )
- ResourceRegistryStandardImpl # register -> M56_01
1 | java复制代码// Step 1 : 核心中间处理器 |
executeUpdate 处理流程
- ResultSetReturnImpl # executeUpdate
- HikariProxyPreparedStatement # executeUpdate
- ProxyPreparedStatement # executeUpdate
- ClientPreparedStatement # executeUpdate
- ClientPreparedStatement # executeLargeUpdate
- ClientPreparedStatement # executeUpdateInternal
- ClientPreparedStatement # fillSendPacket
1 | java复制代码C58- SessionEventListenerManagerImpl |
M60_01 源代码 : bindvalue 的绑定处理
1 | java复制代码public <M extends Message> M fillSendPacket(QueryBindings<?> bindings) { |
PS:M60_01_01 : bindValue 对应参数
2.2 补充节点 : OriginSQL 的生成
我把 staticSqlStrings 称为 OriginSQL , 把 sendPacket 的 SQL 称为 NativeSQL
OriginSQL 的前世今生
上文从 this.parseInfo.getStaticSql() 中获取的 SQL 实际上已经被切割好了 , 我们从源头看看是什么时候放进去的 :
1 | java复制代码// 先看一下体系 |
来吧 , 非要把这一段代码看一遍 ,按照 Step 过一遍就行
1 | java复制代码 public ParseInfo(String sql, Session session, String encoding, boolean buildRewriteInfo) { |
2.3 Entity 转换为 SQL
即实体类转换为
insert into user (isactive, orgid, remark, userlink, username, usertype, userid) values (?, ?, ?, ?, ?, ?, ?)
1 | java复制代码 |
PS:M53_01_01 AbstractEntityPersister 中的默认语句
从图片中就不难发现 , AbstractEntityPersister 中已经预先生成了相关的属性 , 直接获取
流程
1 | java复制代码// 这些属性值是在以下流程中生成得 : |
实际生成方法 源代码
1 | java复制代码C53- AbstractEntityPersister |
总结
整体有三个节点 :
解析的实际节点 : ClientPreparedStatement # fillSendPacket
SQL 的处理 : ParseInfo
Entity 翻译为 SQL : AbstractEntityPersister # generateInsertString
本文转载自: 掘金