原标题:SpringCertification|SpringDataJDBC-如何第一次使用自定义ID生成。如果您是SpringDataJDBC的新手,您应该首先阅读它的介绍和文章,其中解释了SpringDataJDBC上下文中的依赖关系。相信我,这很重要。文章部分基于我在2021年春季刊中为这篇文章所做的演讲。使用ID-特别是当你想控制实体的ID并且不会选择什么数据库时,你有什么选择。在假设的情况下,类型数据列JDBC的假定ID是通过生成SERIAL或AUTOINCREMENT获得的,聚合根执行插入操作。数据库生成一个ID,由SpringDataJDBC在聚合根中设置。考虑一个由单个简单类组成的简单聚合:classMinion{@IDlongID;字符串名称;Minion(Stringname){this.name=name;}}进一步考虑默认的CrudRepository。interfaceMinionRepositoryextendsCrudRepository{}存储库会像这样自动连接到您的代码中:@autowireMinionRepositoryfollower;以下工作正常:Minionbefore=newMinion("Bob");assertThat(before.id)。isNull();Minionafter=minions.save(before);assertThat(after.id).isNotNull();但下一位:Minionbefore=newMinion("Stuart");before.id=42L;minions.save(前);update语句,SpringDataJDBC尝试执行更新,因为ID已经设置。但是,由于更新语句影响零行,SpringDataJDBC抛出异常,因为它实际上是新的。有几种方法可以解决这个问题。我找到了您的不同解决方法,并且找到了我认为最简单的方法,所以找出有效的方法,您就可以停止阅读了。稍后回来阅读其他选项并提高您的SpringData技能。版本将版本属性添加到您的聚合属性。“版本属性”是指@Version。这个类的主要目的是启用乐观锁定。但是,作为一个属性,SpringDataJDBC使用版本属性来判断聚合根是否是新的。只要原始类型的版本为null或0,聚合就被认为是新的,即使设置了id。使用这种方法,您必须更改实体和(当然)系统,但别无其他。此外,对于许多应用程序,最初乐观很多。我们将原始的Minion变成了VersionedMinion:classVersionedMinion{@IdlongID;字符串名称;@Version整数版本;VersionedMinion(longID,stringname){this.id=id;this.name=名称;}}通过此更改,以下结构有效:VersionedMinionbefore=newVersionedMinion(23L,"Bob");assertThat(before.id).isNotNull();versionedMinions.save(before);VersionedMinionreload=versionedMinions.findById(在.id).get();assertThat(reloaded.name).isEqualTo("Bob");之前样板将ID附加到遗赠的一种方法是自己插入另一个插入物。您可以通过注入JdbcAggregateTemplate并调用JdbcAggregateTemplate.insert(T)来完成此操作。这个JdbAggregateTemplate是存储库下面的底层,因此您使用存储库用于插入的相同代码,但您决定何时使用插入:Minionbefore=newMinion("Stuart");before.id=42L;模板.插入(之前);Minion重新加载=minions.findById(42L).get();assertThat(reloaded.name).isEqualTo("斯图尔特");请注意,我们不使用repositoryfarm使用模板,它会注入以下内容:@TheautowiredJdbcAggregateTemplate模板;事件侦听器模板方法非常适合您已经知道ID的情况-例如,当您从另一个系统导入数据并且想要重用该系统的ID时。如果您不知道ID并且不想在您的业务代码中包含任何与ID相关的内容,那么使用ID可能是更好的选择。我们的目的正确的目的是在某些生命周期事件期间被调用的bean。它返回修改后的底层聚合根,因此它也适用于不构成实体的类。在目标中,我们确定有问题的聚合根是否需要新ID。如果是这样,我们将使用我们选择的算法生成它。我们使用另一个变体MinionclassStringIdMinion{@IDstringid;字符串名称;StringIdMinion(字符串名称){this.name=name;然而,我们在配置中注册了一个惊人的例子:@beans,lentilsBeforeSaveCallbackbeforeSaveCallback(){return(minion,mutableAggregateChange)->{if(minion.id==null){minion.id=UUID.randomUUID().toString();}返回奴才;};}保存实体代码现在看起来像是由数据库生成的:StringIdMinionbefore=newStringIdMinion("Kevin");stringions.save(before);assertThat(before.id).isNotNull();StringIdMinionreloaded=stringions.findById(在.id之前).get();assertThat(reloaded.name).isEqualTo("Kevin");持久性的一种选择是让根控制它是否应该更新或插入。您可以实施持久性方法(尤其是如果实施是新的)来实现这一点。当您还想使用聚合根进行更新时,就会出现这种情况。在这种情况下,您需要想出一个更灵活的策略。我们需要Minion再次调整我们的:classPersistableMinionimplementsPersistable{@IdlongID;字符串名称;PersistableMinion(longID,Stringname){this.id=id;this.name=名称;}@overridepubliclonggetId(){返回ID;}@overridepublicbooleanisNew(){//这个实现绝对不适合生产使用returntrue;保存一个PersistableMinion的代码看起来是一样的:reloaded.name).isEqualTo("Dave");结论SpringDataJDBC提供了很多关于Options如何控制聚合ID的信息。虽然我在示例中使用了相当繁重的逻辑,但基本上没有什么可以阻止您实现您想到的任何逻辑,因为它们都归结为Java代码。完整的示例代码可以在Spring中国教育管理中心(Spring认证)数据示例库中获取!
