如何使用 Mono<Connection> 或 R2dbc 在 Spring 中提供的 DatabaseClient 处理可为空的字段?
How do I handle nullable fields using either the Mono<Connection> or the DatabaseClient provided by R2dbc in Spring?
我不知道如何使用 spring-webflux(反应式)在 R2dbc (java) 中构建高效查询。使用 R2dbc 提供的 DatabaseClient 对象(或者 Connection 对象),我似乎只能调用这两种方法之一的不同变体:bind(Object field, Object value)
或 bindNull(Object field, Class<?> type)
。如果我有一个模式,并且在 Java 中有一个对应的 class,具有多个可为空的字段,我应该如何[有点] 有效地处理这个问题?
举个例子:
public Flux<Item> saveOrUpdate(Item entity) {
Mono<Connection> connection = this.connection;
Flux<? extends Result> itemFlux = connection
.doOnError(e -> e.printStackTrace())
.flatMapMany(connect -> connect.createStatement(INSERT_OR_UPDATE_ITEM)
.bind("itemId", entity.getItemId()).returnGeneratedValues("itemid")
.bind("auditId", entity.getTx().getId())
.bind("itemNum", entity.getItemNum())
.bind("itemCat", entity.getItemCat()) //nullable
// How would I know when to use this?
.bindNull("sourcedQty", Integer.class) //nullable
.bind("makeQty", entity.getMakeQty())
.bind("nameShown", entity.getNameShown()) //nullable
.bind("price", entity.price())
.bind("dateCreated", entity.getDateCreated()) //nullable
.add()
.execute())...
...
}
或
public Mono<Item> saveOrUpdate(Item entity){
Mono<Item> itemMono = databaseClient.execute.sql(INSERT_OR_UPDATE_ITEM)
.bind("itemId", entity.getItemId()).returnGeneratedValues("itemid")
.bind("auditId", entity.getTx().getId())
.bind("itemNum", entity.getItemNum())
.bind("itemCat", entity.getItemCat())
.bind("sourcedQty", entity.getSourcedQty())
.bind("makeQty", entity.getMakeQty())
.bind("nameShown", entity.getNameShown())
.bind("price", entity.price())
.bind("dateCreated", entity.getDateCreated())
.as(Item.class)
.fetch()
.one()...
...
}
对于可为空的字段,我当然可以用 .bindNull 替换 .bind。问题是如果我调用 bind,该值不能为 null。如果我调用 bindNull,则该值必须为 null。我如何才能根据我的值实际上是否为空来调用一个或另一个?我已经知道我可以为每个场景制作一堆方法或按照 retryOnError 的方式调用一些方法。但是,如果我想做一个 insertOrUpdate(List<Item> items)
,这将浪费大量的 time/resources。理想情况下,我想以某种方式在某处做一些类似于 if (field == null) ? bindNull("field", field.class) : bind("field", myObj.field)
的事情。如果这显然不符合 table,我仍然有兴趣找出一种方法来尽可能有效地实现它,因为我正在使用它。感谢任何反馈。
这是两个问题:
- 如何以流畅的方式将可能为 null 的值绑定到
Statement
/DatabaseClient
?
- 如何让数据库算出其余部分?
R2DBC 和 Spring 数据 R2DBC 通过要求将值绑定到 Statement
或绑定 null
使 null
处理显式。没有接受可能为 null 的参数的方法。有两个原因:
- 您应该处理可空性以使那里发生的事情显而易见。这是处理可空值而不是隐式处理
null
的好习惯。 null
的隐含性质是导致错误最多的原因。
- 数据库要求明确。带占位符的参数化语句包含在两个块的执行端:SQL 语句本身和参数绑定(描述符)。参数描述符需要与占位符、类型信息(
VARCHAR
、BIT
、INT
、…)和实际值的关联。通过使用值调用 bind(…)
,驱动程序可以导出类型信息。绑定 null
值时,驱动程序需要其他类型的信息。否则,我们无法执行查询。
也就是说:
- 没有API像
bindPotentiallyNull("auditId", entity.getTx().getId(), Integer.class)
- 您不能在 SQL 查询中执行任何操作,因为绑定参数信息是由辅助方法提供的。
我们在谈论存储过程时面临类似的问题,因为存储过程需要有关 in/out/in-out 参数的其他详细信息。我们讨论了潜在的包装器类型,例如
Parameters.in(@Nullable T value, Class<? super T> valueType)
所以这些可以用作
中的包装器
bind("auditId", Parameters.in(entity.getTx().getId(), Integer.class))
更多详情:
可以使用 Parameter
class 设置值或空值,如下所示:
import org.springframework.r2dbc.core.Parameter;
// rest of the code
.bind("customerId", Parameter.fromOrEmpty(o.getCustomerId(), UUID.class))
之前是SettableValue.fromOrEmpty
,现在还没有弃用。
我不知道如何使用 spring-webflux(反应式)在 R2dbc (java) 中构建高效查询。使用 R2dbc 提供的 DatabaseClient 对象(或者 Connection 对象),我似乎只能调用这两种方法之一的不同变体:bind(Object field, Object value)
或 bindNull(Object field, Class<?> type)
。如果我有一个模式,并且在 Java 中有一个对应的 class,具有多个可为空的字段,我应该如何[有点] 有效地处理这个问题?
举个例子:
public Flux<Item> saveOrUpdate(Item entity) {
Mono<Connection> connection = this.connection;
Flux<? extends Result> itemFlux = connection
.doOnError(e -> e.printStackTrace())
.flatMapMany(connect -> connect.createStatement(INSERT_OR_UPDATE_ITEM)
.bind("itemId", entity.getItemId()).returnGeneratedValues("itemid")
.bind("auditId", entity.getTx().getId())
.bind("itemNum", entity.getItemNum())
.bind("itemCat", entity.getItemCat()) //nullable
// How would I know when to use this?
.bindNull("sourcedQty", Integer.class) //nullable
.bind("makeQty", entity.getMakeQty())
.bind("nameShown", entity.getNameShown()) //nullable
.bind("price", entity.price())
.bind("dateCreated", entity.getDateCreated()) //nullable
.add()
.execute())...
...
}
或
public Mono<Item> saveOrUpdate(Item entity){
Mono<Item> itemMono = databaseClient.execute.sql(INSERT_OR_UPDATE_ITEM)
.bind("itemId", entity.getItemId()).returnGeneratedValues("itemid")
.bind("auditId", entity.getTx().getId())
.bind("itemNum", entity.getItemNum())
.bind("itemCat", entity.getItemCat())
.bind("sourcedQty", entity.getSourcedQty())
.bind("makeQty", entity.getMakeQty())
.bind("nameShown", entity.getNameShown())
.bind("price", entity.price())
.bind("dateCreated", entity.getDateCreated())
.as(Item.class)
.fetch()
.one()...
...
}
对于可为空的字段,我当然可以用 .bindNull 替换 .bind。问题是如果我调用 bind,该值不能为 null。如果我调用 bindNull,则该值必须为 null。我如何才能根据我的值实际上是否为空来调用一个或另一个?我已经知道我可以为每个场景制作一堆方法或按照 retryOnError 的方式调用一些方法。但是,如果我想做一个 insertOrUpdate(List<Item> items)
,这将浪费大量的 time/resources。理想情况下,我想以某种方式在某处做一些类似于 if (field == null) ? bindNull("field", field.class) : bind("field", myObj.field)
的事情。如果这显然不符合 table,我仍然有兴趣找出一种方法来尽可能有效地实现它,因为我正在使用它。感谢任何反馈。
这是两个问题:
- 如何以流畅的方式将可能为 null 的值绑定到
Statement
/DatabaseClient
? - 如何让数据库算出其余部分?
R2DBC 和 Spring 数据 R2DBC 通过要求将值绑定到 Statement
或绑定 null
使 null
处理显式。没有接受可能为 null 的参数的方法。有两个原因:
- 您应该处理可空性以使那里发生的事情显而易见。这是处理可空值而不是隐式处理
null
的好习惯。null
的隐含性质是导致错误最多的原因。 - 数据库要求明确。带占位符的参数化语句包含在两个块的执行端:SQL 语句本身和参数绑定(描述符)。参数描述符需要与占位符、类型信息(
VARCHAR
、BIT
、INT
、…)和实际值的关联。通过使用值调用bind(…)
,驱动程序可以导出类型信息。绑定null
值时,驱动程序需要其他类型的信息。否则,我们无法执行查询。
也就是说:
- 没有API像
bindPotentiallyNull("auditId", entity.getTx().getId(), Integer.class)
- 您不能在 SQL 查询中执行任何操作,因为绑定参数信息是由辅助方法提供的。
我们在谈论存储过程时面临类似的问题,因为存储过程需要有关 in/out/in-out 参数的其他详细信息。我们讨论了潜在的包装器类型,例如
Parameters.in(@Nullable T value, Class<? super T> valueType)
所以这些可以用作
中的包装器bind("auditId", Parameters.in(entity.getTx().getId(), Integer.class))
更多详情:
可以使用 Parameter
class 设置值或空值,如下所示:
import org.springframework.r2dbc.core.Parameter;
// rest of the code
.bind("customerId", Parameter.fromOrEmpty(o.getCustomerId(), UUID.class))
之前是SettableValue.fromOrEmpty
,现在还没有弃用。