0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Spring Data JDBC - 如何使用自定义ID

「Spring」认证安全架构 来源:「Spring」认证安全架构 作者:「Spring」认证安全 2022-06-28 16:18 次阅读

原标题:Spring认证|Spring Data JDBC-如何使用自定义ID生成

这是关于如何解决使用 Spring Data JDBC 时可能遇到的各种挑战的系列文章的第一篇。

如果你不了解 Spring Data JDBC,你应该首先阅读它的介绍和文章,它解释了 Spring Data JDBC 上下文中的相关性。相信我,这很重要。

文章基于我在 2021 年春季一期上这篇文章的部分演讲。

使用 ID - 特别是当您想要控制实体的 ID 并且不会选择什么数据库时,您的选择是什么。

假设情况下,类型数据列JDBC假设的ID通过生成SERIAL或AUTOINCREMENT得到。 ,聚合根执行插入操作。数据库生成一个ID,这个ID由Spring Data JDBC在聚合根中设置。

考虑一个由单个简单的类组成的简单聚合:

类小黄人{

@ID

长ID;

字符串名称;

Minion(字符串名称){

this.name = 名称;

}

}

进一步考虑默认CrudRepository。

接口 MinionRepository 扩展 CrudRepository {

}

存储库会自动连接到您的代码中,如下所示:

@自动连线

MinionRepository 随从;

以下工作正常:

Minion before = new Minion("Bob");

assertThat(before.id).isNull();

Minion after = minions.save(before);

assertThat(after.id).isNotNull();

但是下一点点:

Minion before = new Minion("Stuart");

before.id = 42L;

minions.save(before);

更新语句,Spring Data JDBC 尝试执行更新,因为 ID 已经设置。但是,因为实际上是新的,更新语句影响零行 Spring Data JDBC 抛出异常。

有几种方法可以解决这个问题。我已经找到了你不同的解决方法,并且已经找到了我认为最简单的方法,因此可以找到适合的方法,你就可以停止阅读。之后回来阅读其他选项并提高您的 Spring Data 技能。

版本

将版本属性添加到您的聚合属性。“版本属性”是指用@Version。此类的主要目的是可以乐观锁定。但是,作为属性,Spring Data JDBC 使用版本属性来确定聚合根是否是新的。 只要版本是null 或0 原始类型,聚合就被认为是新的,即使id设置了。

使用这种方法,您必须更改实体和(当然)系统,但别无其他。

此外,对于许多应用程序来说,乐观的最初是很多。

我们把原来的Minion变成了一个VersionedMinion:

类 VersionedMinion {

@Id 长 ID;

字符串名称;

@Version 整数版本;

VersionedMinion(长ID,字符串名称){

this.id = id;

this.name = 名称;

}

}

通过此更改,以下构造有效:

VersionedMinion before = new VersionedMinion(23L, "Bob");

assertThat(before.id).isNotNull();

versionedMinions.save(before);

VersionedMinion 重新加载 = versionedMinions.findById(before.id).get();

assertThat(reloaded.name).isEqualTo("Bob");

样板

一种让您的遗赠附带 ID 的方法是自己另外插入物。您可以通过注入 JdbcAggregateTemplate 并调用 JdbcAggregateTemplate.insert(T)。这JdbAggregateTemplate是存储库下面的底层,因此您使用存储库用于插入的相同代码,但您决定何时使用插入:

Minion before = new Minion("Stuart");

before.id = 42L;

模板.插入(之前);

Minion reloaded = minions.findById(42L).get();

assertThat(reloaded.name).isEqualTo("Stuart");

请注意,我们不使用存储库农场使用模板,其中注入了以下内容:

@自动连线

JdbcAggregateTemplate 模板;

事件监听器

模板方法非常适用于您已经知道 ID 的情况 - 例如,当您从另一个系统导入数据并且您想要重用该系统的 ID 时。

如果您不知道 ID 并且不想在您的业务代码中包含任何 ID 相关的内容,那么使用 ID 可能是更好的选择。

我们的目的正确的目的是在某些生命周期事件期间被调用的豆子。它返回修改潜在的聚合根,因此它也适用于不形成实体类。

在目标中,我们确定有问题的聚合根是否需要新 ID。 如果是这样,我们将使用我们选择的算法生成它。

我们使用另一种变体 Minion

类 StringIdMinion {

@ID

字符串标识;

字符串名称;

StringIdMinion(字符串名称){

this.name = 名称;

}

}

但是,我们在配置中注册了一个惊人的例子:

@豆角,扁豆

BeforeSaveCallback beforeSaveCallback() {

返回(minion,mutableAggregateChange)-> {

如果(minion.id == null){

minion.id = UUID.randomUUID().toString();

}

返回仆从;

};

}

保存实体的代码现在看起来就像是由数据库生成的:

StringIdMinion before = new StringIdMinion("Kevin");

stringions.save(before);

assertThat(before.id).isNotNull();

StringIdMinion reloaded = stringions.findById(before.id).get();

assertThat(reloaded.name).isEqualTo("Kevin");

持久的

一个选项是让化根控制是否应该更新或插入。你可以实现持久化的方法(尤其是实现是新的)来实现这一点。您也想使用聚合根进行更新时,这会抓住。在这种情况下,您需要提出更灵活的策略。

我们需要 Minion 再次调整我们的:

类 PersistableMinion 实现 Persistable {

@Id 长 ID;

字符串名称;

PersistableMinion(长ID,字符串名称){

this.id = id;

this.name = 名称;

}

@覆盖

公共长 getId() {

返回标识;

}

@覆盖

公共布尔 isNew() {

// 这个实现肯定不适合生产使用

返回真;

}

}

保存一个的代码 PersistableMinion 看起来是一样的:

PersistableMinion before = new PersistableMinion(23L, "Dave");

persistableMinions.save(before);

PersistableMinion 重新加载 = persistableMinions.findById(before.id).get();

assertThat(reloaded.name).isEqualTo("Dave");

结论

Spring Data JDBC 提供了大量关于如何控制聚合 ID 的选项。虽然我在示例中使用了非常严重的逻辑,但基本没有什么能阻止您实现您所考虑的任何逻辑,因为它们都归结为 Java 代码。

完整的示例代码可在Spring中国教育管理中心(Spring认证)数据示例库访问!

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • spring
    +关注

    关注

    0

    文章

    340

    浏览量

    14334
  • JDBC
    +关注

    关注

    0

    文章

    25

    浏览量

    13399
收藏 人收藏

    评论

    相关推荐

    TPS659xx应用程序自定义工具

    电子发烧友网站提供《TPS659xx应用程序自定义工具.pdf》资料免费下载
    发表于 11-06 10:02 0次下载
    TPS659xx应用程序<b class='flag-5'>自定义</b>工具

    创建自定义的基于闪存的引导加载程序(BSL)

    电子发烧友网站提供《创建自定义的基于闪存的引导加载程序(BSL).pdf》资料免费下载
    发表于 09-19 10:50 0次下载
    创建<b class='flag-5'>自定义</b>的基于闪存的引导加载程序(BSL)

    如何创建TestStand自定义步骤

    在之前的课程中简单地介绍过TestStand自带的一些步骤类型,如测试、消息弹窗、赋值、标签等等,这些简单的步骤从TestStand的插入选版中就可以添加到序列中。那么在使用中如果碰到需要实现更加灵活、复杂的功能,使用自带的一些步骤类型可能难以满足,这时就需要使用到自定义步骤。
    的头像 发表于 09-11 14:46 1032次阅读
    如何创建TestStand<b class='flag-5'>自定义</b>步骤

    EtherCAT运动控制器PT/PVT实现用户自定义轨迹规划

    EtherCAT运动控制器PT/PVT实现用户自定义轨迹规划。
    的头像 发表于 08-15 11:49 609次阅读
    EtherCAT运动控制器PT/PVT实现用户<b class='flag-5'>自定义</b>轨迹规划

    NVIDIA NeMo加速并简化自定义模型开发

    如果企业希望充分发挥出 AI 的力量,就需要根据其行业需求量身定制的自定义模型。
    的头像 发表于 07-26 11:17 740次阅读
    NVIDIA NeMo加速并简化<b class='flag-5'>自定义</b>模型开发

    Chrome移动版支持自定义菜单栏功能

    在先前版本中,用户通过点击浏览器右上角的三个点按钮即可调出包含各类图标与操作的菜单。而此次更新后,Chrome新增了“自定义菜单”选项,允许用户自主控制该区域的展示内容。
    的头像 发表于 05-27 15:00 790次阅读

    HarmonyOS开发案例:【 自定义弹窗】

    基于ArkTS的声明式开发范式实现了三种不同的弹窗,第一种直接使用公共组件,后两种使用CustomDialogController实现自定义弹窗
    的头像 发表于 05-16 18:18 1344次阅读
    HarmonyOS开发案例:【 <b class='flag-5'>自定义</b>弹窗】

    TSMaster 自定义 LIN 调度表编程指导

    LIN(LocalInterconnectNetwork)协议调度表是用于LIN总线通信中的消息调度的一种机制,我们收到越来越多来自不同用户希望能够通过接口实现自定义LIN调度表的需求。所以在
    的头像 发表于 05-11 08:21 650次阅读
    TSMaster <b class='flag-5'>自定义</b> LIN 调度表编程指导

    HarmonyOS开发案例:【UIAbility和自定义组件生命周期】

    本文档主要描述了应用运行过程中UIAbility和自定义组件的生命周期。对于UIAbility,描述了Create、Foreground、Background、Destroy四种生命周期。对于页面
    的头像 发表于 05-10 15:31 1236次阅读
    HarmonyOS开发案例:【UIAbility和<b class='flag-5'>自定义</b>组件生命周期】

    微软Dev Home应用提供自定义文件管理支持

    据悉,Microsoft 近期发布了 0.13 版 Dev Home 应用程序,除修复多项 BUG 外,还新增了自定义文件资源管理器功能。该应用支持用户在应用内创建虚拟机,利用微软旗下的 Hyper V 技术生成本地虚拟机。
    的头像 发表于 04-26 11:15 452次阅读

    HarmonyOS开发实例:【自定义Emitter】

    使用[Emitter]实现事件的订阅和发布,使用[自定义弹窗]设置广告信息。
    的头像 发表于 04-14 11:37 993次阅读
    HarmonyOS开发实例:【<b class='flag-5'>自定义</b>Emitter】

    鸿蒙ArkUI实例:【自定义组件】

    组件是 OpenHarmony 页面最小显示单元,一个页面可由多个组件组合而成,也可只由一个组件组合而成,这些组件可以是ArkUI开发框架自带系统组件,比如 `Text` 、 `Button` 等,也可以是自定义组件,本节笔者简单介绍一下自定义组件的语法规范。
    的头像 发表于 04-08 10:17 621次阅读

    pSoC63的sflash_user_data能用作用户自定义的flash吗?

    给第一行写了自定义的数据,我发现可以写入。 程序运行也没发现啥问题。 我想请教一下这部分真的不能用作用户自定义的flash吗?我只想用1行,512字节写点数据。 是否可以?谢谢!
    发表于 02-21 07:00

    基于YOLOv8实现自定义姿态评估模型训练

    Hello大家好,今天给大家分享一下如何基于YOLOv8姿态评估模型,实现在自定义数据集上,完成自定义姿态评估模型的训练与推理。
    的头像 发表于 12-25 11:29 2831次阅读
    基于YOLOv8实现<b class='flag-5'>自定义</b>姿态评估模型训练

    博途用户自定义库的使用

    博途官方提供了很多库,比如:基本函数库、通信库、安全库、驱动库等等,用户可以使用库中的函数/函数块来完成具体的控制任务。除了官方的库,我们也可以创建自己的库(用户自定义库)。比如,把项目
    的头像 发表于 12-25 10:08 908次阅读
    博途用户<b class='flag-5'>自定义</b>库的使用