首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

源码分析 Hibernate 是如何获取到插入数据库后的记录ID

测试

首先,我们通过一下代码测试今天分析的主题:hibernate 在 save 后会将 id 回写到实体类。

引入 hibernate 的 jar 包,我使用的是 hibernate 5.3.7.Final 版本:

新建一个实体类(省略掉了 getter 和 setter 方法):

在 resources/orm 下新增 hibernate 的配置文件,如下:

我们通过以下方法进行测试:

测试结果如下:

从结果可以看出,在调用后插入记录的 id 已经被自动设置到 user 对象上了。

分析

我以 MySQL 的主键自增字段为例来分析,直接上图:

上图就是完整的调用方法后的hibernate代码执行逻辑。

下面我们一步步分析具体是如何执行的。

SessionImpl

当调用 时,会执行 Session 的实现类 SessionImpl 的 save 方法:

最终会调用 fireSave 方法,传入一个 SaveOrUpdateEvent 事件,在 fireSave 方法,会触发 SaveOrUpdateEventListener 监听器,执行 SaveOrUpdateEventListener.onSaveOrUpdate onSaveOrUpdate方法。

DefaultSaveOrUpdateEventListener

SaveOrUpdateEventListener 是个接口,默认实现类为 DefaultSaveOrUpdateEventListener,onSaveOrUpdate 方法会执行 该类的 performSaveOrUpdate 方法

这里会根据对象的不同状态执行不同的逻辑:

托管态:执行 entityIsDetached

持久态:执行 entityIsPersistent

自由态:执行 entityIsTransient

我们主要看自由态的对象保存时的逻辑,所以我们继续看 entityIsTransient 方法:

通过上面的代码我们看到这个方法又会调用该类的 saveWithGeneratedOrRequestedId 方法,而 saveWithGeneratedOrRequestedId 会直接调用父类 AbstractSaveEventListener.saveWithGeneratedId 方法。

AbstractSaveEventListener

saveWithGeneratedId 这个方法比较关键,我们具体分析一下:

其中这行代码,会根据实体类的ID字段的ID生成策略定义分析如何生成ID。

比如我们定义使用UUID作为ID生成策略:

那么上面的 generate 方法会直接返回一个 uuid 字符串;如果像我之前在实体类上定义的数据库自增ID生成策略,则会返回 ,这样的话会走 这个方法执行插入操作。

注:persister.getIdentifierGenerator() 获取的是在hibernate启动时分析配置文件后解析对应的实体类后生成的实体类元数据,如果想了解,可以跟踪下hibernate的启动过程。

performSave 方法最后又会调用 performSaveOrReplicate 方法,我摘出这个方法比较重要的部分如下:

通过名称我们可以看到 cascadeBeforeSave 表示在保存前的级联操作, cascadeAfterSave 表示在保存后的级联操作,那么中间的 addInsertAction 方法就会操作数据库执行保存动作了。

useIdentityColumn 参数,我们通过下面的截图可以看到尾 true,将会走 if 逻辑,创建 EntityIdentityInsertAction 对象,并加入到 ActionQueue 中。

ActionQueue

进入该类以后,会执行 addInsertAction 方法,最后会调用刚加入队列的 EntityIdentityInsertAction 的 execute 方法。

EntityIdentityInsertAction

经历了上面那么多逻辑以后,终于,我们的实体类要执行插入操作了:

这里有两个步骤:

1.插入数据库并返回ID

这行代码会调用实体持久化器,操作数据库:

AbstractReturningDelegate

这行代码会调用类 GetGeneratedKeysDelegate 的 executeAndExtract 方法:

好了,到此为止,hibernate就完成了整个实体保存操作,并返回了生成的ID。

2.将返回的ID设置到实体类对应字段上

这行代码会通过反射将生成的ID设置到实体类对应字段上。代码比较简单,具体可继续跟进了解。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181221G13BTS00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券