Java 使用Spring数据R2DBC执行大容量插入时检索生成的ID
我有一个场景,我的表有一个自动生成的id列,我需要将项目批量插入数据库并获取生成的id。我有没有办法做到这一点 这是我的桌子:Java 使用Spring数据R2DBC执行大容量插入时检索生成的ID,java,mysql,spring-boot,spring-webflux,spring-data-r2dbc,Java,Mysql,Spring Boot,Spring Webflux,Spring Data R2dbc,我有一个场景,我的表有一个自动生成的id列,我需要将项目批量插入数据库并获取生成的id。我有没有办法做到这一点 这是我的桌子: CREATE TABLE test_table ( `id` SERIAL NOT NULL, `name` VARCHAR(100) NOT NULL, `created_date` DATETIME NOT NULL, PRIMARY KEY (`id`) ); 要将项目列表保存到此表中,我使用的代码为: String initialSql = &
CREATE TABLE test_table (
`id` SERIAL NOT NULL,
`name` VARCHAR(100) NOT NULL,
`created_date` DATETIME NOT NULL,
PRIMARY KEY (`id`)
);
要将项目列表保存到此表中,我使用的代码为:
String initialSql = "INSERT INTO test_table(`name`,`created_date`) VALUES ";
List<String> values =
dummyEntities.stream()
.map(dummyEntity -> "('" + dummyEntity.getName() + "','"
+ dummyEntity.getCreatedDate().atZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime().toString() + "')")
.collect(Collectors.toList());
String sqlToExecute = initialSql + String.join(",", values);
client.execute(sqlToExecute)
.//Then what?
我甚至尝试过使用连接工厂
,但仍然没有任何线索
Mono.from(connectionFactory.create())
.map(Connection::createBatch)
.map(batch -> {
dummyEntities.forEach(dummyEntity -> {
String sql = String.format("INSERT INTO `test_table` (`name`,`created_date`) VALUES ('%s','%s');", dummyEntity.getName(),
dummyEntity.getCreatedDate().atZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime().toString());
batch.add(sql);
});
return batch;
})
.flatMap(batch -> Mono.from(batch.execute()))
.//Then what?
作为参考,dummeyentities
变量包含dummeyentity
对象的列表。而dummeyentity
类如下所示:
@Table("test_table")
public class DummyEntity implements Persistable<Long> {
@Id
@Column("id")
private Long id;
@Column("name")
private String name;
@Column("created_date")
private OffsetDateTime createdDate;
//Getter,Setter
@Override
public boolean isNew() {
return id == null;
}
}
使用原始的
连接factory
很容易获得生成的ID
我尝试使用ConnectionFactory
获取生成的ID,并按预期工作
。然后很多(
单声道,从(康涅狄格州)
flatMapMany先生(
c->c.createStatement(插入SQL)
.returnGeneratedValues(“id”)
.execute()
)
)
.flatMap(data->Flux.from(data.map((行,行元数据)->row.get(“id”))
.doOnNext(id->log.info(“生成的id:{}”,id))
完整的代码示例如下所示
它像这样在控制台中打印日志
2020-09-19 10:43:30815 INFO[main]com.example.demo.H2Tests$Sql:89生成的id:1
2020-09-19 10:43:30815 INFO[main]com.example.demo.H2Tests$Sql:89生成的id:2
我认为SpringFramework5.3中新的DatabaseClient
只是ConnectionFactorys的一个薄包装,并使用filter
获得生成的ID
databaseClient.sql(“插入帖子(标题、内容、元数据)值(:标题、内容、元数据)”)
.filter((语句,executeFunction)->语句.returnGeneratedValues(“id”).execute()
检查(但本例仅检索单个id)。使用原始的
连接facotory
很容易获得生成的id
我尝试使用ConnectionFactory
获取生成的ID,并按预期工作
。然后很多(
单声道,从(康涅狄格州)
flatMapMany先生(
c->c.createStatement(插入SQL)
.returnGeneratedValues(“id”)
.execute()
)
)
.flatMap(data->Flux.from(data.map((行,行元数据)->row.get(“id”))
.doOnNext(id->log.info(“生成的id:{}”,id))
完整的代码示例如下所示
它像这样在控制台中打印日志
2020-09-19 10:43:30815 INFO[main]com.example.demo.H2Tests$Sql:89生成的id:1
2020-09-19 10:43:30815 INFO[main]com.example.demo.H2Tests$Sql:89生成的id:2
我认为SpringFramework5.3中新的DatabaseClient
只是ConnectionFactorys的一个薄包装,并使用filter
获得生成的ID
databaseClient.sql(“插入帖子(标题、内容、元数据)值(:标题、内容、元数据)”)
.filter((语句,executeFunction)->语句.returnGeneratedValues(“id”).execute()
检查(但本例仅检索单个id)。稍后的响应,但由于我在R2DBC PostgreSQL上遇到了相同的问题,因此有一个可能的解决方案:
// -- generate 100 Product entities and mark them as CREATE
// -- Product is implementing Persistable<UUID> and isNew() will return TRUE for CREATE and FALSE for UPDATE
List<Product> list = Stream.generate(() -> Product.builder()
.articleNumber(UUID.randomUUID().toString().substring(0, 10))
.name(UUID.randomUUID().toString())
.images(Arrays.asList("1", "2"))
.saveAction(SaveAction.CREATE)
.build()).limit(100).collect(Collectors.toList());
// -- create the PostgresqlBatch and return the Result flux
Flux<? extends Result> flux = databaseClient.inConnectionMany(connection -> {
Batch batch = connection.createBatch();
list.forEach(p -> {
batch.add("INSERT INTO product(\"id\",\"article_number\",\"name\") VALUES ('" + p.getId() + "','" + p.getArticleNumber() + "','" + p
.getName() + "') RETURNING id, name, article_number");
});
return Flux.from(batch.execute());
});
// -- transform the Result flux into a Product flux
return flux.flatMap(result -> result.map((row, rowMetadata) -> Product.builder()
.id(row.get("id", UUID.class))
.name(row.get("name", String.class))
.articleNumber(row.get("article_number", String.class))
.build()));
/--生成100个产品实体并将其标记为CREATE
//--产品正在实现Persistable,isNew()将为CREATE返回TRUE,为UPDATE返回FALSE
List List=Stream.generate(()->Product.builder()
.articleNumber(UUID.randomUUID().toString().substring(0,10))
.name(UUID.randomUUID().toString())
.images(数组.asList(“1”、“2”))
.saveAction(saveAction.CREATE)
.build()).limit(100.collect(Collectors.toList());
//--创建PostgresqlBatch并返回结果
Flux稍后的响应,但由于我在R2DBC PostgreSQL上遇到了相同的问题,下面是一个可能的解决方案:
// -- generate 100 Product entities and mark them as CREATE
// -- Product is implementing Persistable<UUID> and isNew() will return TRUE for CREATE and FALSE for UPDATE
List<Product> list = Stream.generate(() -> Product.builder()
.articleNumber(UUID.randomUUID().toString().substring(0, 10))
.name(UUID.randomUUID().toString())
.images(Arrays.asList("1", "2"))
.saveAction(SaveAction.CREATE)
.build()).limit(100).collect(Collectors.toList());
// -- create the PostgresqlBatch and return the Result flux
Flux<? extends Result> flux = databaseClient.inConnectionMany(connection -> {
Batch batch = connection.createBatch();
list.forEach(p -> {
batch.add("INSERT INTO product(\"id\",\"article_number\",\"name\") VALUES ('" + p.getId() + "','" + p.getArticleNumber() + "','" + p
.getName() + "') RETURNING id, name, article_number");
});
return Flux.from(batch.execute());
});
// -- transform the Result flux into a Product flux
return flux.flatMap(result -> result.map((row, rowMetadata) -> Product.builder()
.id(row.get("id", UUID.class))
.name(row.get("name", String.class))
.articleNumber(row.get("article_number", String.class))
.build()));
/--生成100个产品实体并将其标记为CREATE
//--产品正在实现Persistable,isNew()将为CREATE返回TRUE,为UPDATE返回FALSE
List List=Stream.generate(()->Product.builder()
.articleNumber(UUID.randomUUID().toString().substring(0,10))
.name(UUID.randomUUID().toString())
.images(数组.asList(“1”、“2”))
.saveAction(saveAction.CREATE)
.build()).limit(100.collect(Collectors.toList());
//--创建PostgresqlBatch并返回结果
Flux您要查找的是client.execute(…).all()
记录在这里,这取决于您返回不同对象的查询,但我认为您要查找的是all()
。您要查找的是client.execute(…).all()
这里的文档记录取决于您返回的不同对象的查询,但我认为它是您正在寻找的all()
。您好@Hantsy,很抱歉响应太晚。我试过你的密码。但它只返回一个生成的id(批处理的第一个id)。在这里查看:。您能指出我在这里做错了什么吗?不确定代码中的确切原因,无法从代码片段中确定。我试过我的代码,它工作正常。你使用的是同一个Miku Mysql驱动程序吗?从您共享的代码片段来看,它是针对H2的。尝试了MySQL,是的,它只返回最后一个id。可能是来自语句last\u insert\u id
。是的,非反应驱动程序如何返回所有生成的id?一定有办法……是不是@Hantsy?嗨@Hantsy,很抱歉这么晚才回复。我试过你的密码。但它只返回一个生成的id(批处理的第一个id)。
// -- generate 100 Product entities and mark them as CREATE
// -- Product is implementing Persistable<UUID> and isNew() will return TRUE for CREATE and FALSE for UPDATE
List<Product> list = Stream.generate(() -> Product.builder()
.articleNumber(UUID.randomUUID().toString().substring(0, 10))
.name(UUID.randomUUID().toString())
.images(Arrays.asList("1", "2"))
.saveAction(SaveAction.CREATE)
.build()).limit(100).collect(Collectors.toList());
// -- create the PostgresqlBatch and return the Result flux
Flux<? extends Result> flux = databaseClient.inConnectionMany(connection -> {
Batch batch = connection.createBatch();
list.forEach(p -> {
batch.add("INSERT INTO product(\"id\",\"article_number\",\"name\") VALUES ('" + p.getId() + "','" + p.getArticleNumber() + "','" + p
.getName() + "') RETURNING id, name, article_number");
});
return Flux.from(batch.execute());
});
// -- transform the Result flux into a Product flux
return flux.flatMap(result -> result.map((row, rowMetadata) -> Product.builder()
.id(row.get("id", UUID.class))
.name(row.get("name", String.class))
.articleNumber(row.get("article_number", String.class))
.build()));