我有一个简单的实体,由两个UUID组成:
@Table("library")
public class LibraryDao {
@Id
private UUID id;
@NonNull
private UUID ownerId;
}我在PostgreSQL中有一个相应的表:
CREATE TABLE IF NOT EXISTS library (id UUID PRIMARY KEY, owner_id UUID NOT NULL);我正在使用正确的R2DBC驱动程序(io.r2dbc:r2dbc-postgresql和org.postgresql:postgresql)。
到目前为止,一切都正常。我的掌声响起了。但是…
因为PostgreSQL (至少根据文档)没有UUID的自动生成函数,所以我在创建新的LibraryDao实例时设置了id。
然而,当我在我的存储库中调用save方法时,我得到了一个异常:Failed to update table [library]. Row with Id [0ed4d7c0-871a-4473-8997-4c9c1ec67a00] does not exist.
save似乎被解释为update,如果它不存在的话,它将不会倒退到insert。
我应该如何在数据库中插入新的记录?
发布于 2022-01-27 15:17:39
尽管有PostgreSQL文档,仍然有一种使用pgcrypto扩展(用于v4 UUID)自动生成UUID的方法。(基于使用pgAdmin GUI的过程。)
在查询工具中:
select * from pg_extension并检查pgcrypto没有列出。create extension pgcrypto来安装它;它附带默认安装。然后,将列定义改为... id UUID PRIMARY KEY DEFAULT gen_random_uuid(), ...
而且它是有效的。
发布于 2022-02-03 13:49:01
因为R2DBC还没有自动生成UUID,而在Spring中使用的工具有自己的机制来防止向DB发送空(因此不能使用触发器来完成这项工作)--也许这里的最佳解决方案是使用UUID.randomUUID();生成UUID,并在将实体发送到DB之前将它们放在实体中。
编辑-具体解决方案:
解决方案的一个小问题是,必须对DB安装进行修改。
在实现了所描述的插入问题之后,我不再尝试使用存储库save方法,而是使用R2DBC DatabaseClient切换到“手动”解决方案。
dbClient.sql("insert into product_price(id, product_id, price) values(:id, :product_id, :price)")
.bind("id", UUID.randomUUID())
.bind("product_id", 1)
.bind("price", 10.0)
.fetch()
.one()
.subscribe();下面是DatabaseClient,它是从ConnectionFactory配置的,启用后可以接受命名参数:
@Bean
public DatabaseClient dbClient(ConnectionFactory connectionFactory) {
return DatabaseClient.builder()
.connectionFactory(connectionFactory)
.namedParameters(true)
.build();
}ConnectionFactory也是我在扩展AbstractR2dbcConfiguration的配置类中公开的易于定制的Bean。
并且希望,反应性存储库中的save()将得到改进,以与其他春季数据存储库中的对应程序相媲美。
发布于 2022-02-04 22:40:52
但是,除了我关于使用R2DBC DatabaseClient执行插入的R2DBC之外,还有一种使用反应性存储库的save方法来实现它的方法--通过使用可持续接口,这是非常直接的。
它的isNew方法可以使用实体的version attribut来实现,或者通过添加一个新的专用attribut (类似于boolean isAlreadyPersisted)来实现,可以在调用save()之前显式地设置它。也许还有其他一些我不知道的使用Persistable的方法。
https://stackoverflow.com/questions/70877916
复制相似问题