[英]How do I handle nullable fields using either the Mono<Connection> or the DatabaseClient provided by R2dbc in Spring?
I am at a loss for how to contruct an efficient query in R2dbc (java) using spring-webflux (reactive).我不知道如何使用 spring-webflux (reactive) 在 R2dbc (java) 中构建有效的查询。 Using the DatabaseClient object provided by R2dbc (or alternatively, a Connection object), it seems that I am only able to call different variations of one of these two methods:
bind(Object field, Object value)
or bindNull(Object field, Class<?> type)
.使用 R2dbc 提供的 DatabaseClient 对象(或一个 Connection 对象),似乎我只能调用这两种方法之一的不同变体:
bind(Object field, Object value)
或bindNull(Object field, Class<?> type)
。 If I have a schema, and a corresponding class in Java, with multiple nullable fields, how am I expected to handle this [somewhat] efficiently?如果我有一个架构和一个对应的 Java 类,有多个可为空的字段,我应该如何[有点]有效地处理这个问题?
Take for example:举个例子:
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())...
...
}
OR或者
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()...
...
}
For my nullable fields I can replace .bind with .bindNull of course.对于我的可为空字段,我当然可以用 .bindNull 替换 .bind 。 The problem is that if I do call bind, the value cannot be null.
问题是,如果我确实调用了绑定,则该值不能为空。 And if I call bindNull, the value must be null.
如果我调用 bindNull,则该值必须为 null。 How would I be able to call one or the other based on whether my value is actually null?
我如何能够根据我的值是否实际上为空来调用一个或另一个? I already know that I can just make a bunch of methods for each scenerio or call something along the lines of retryOnError.
我已经知道我可以为每个场景创建一堆方法或沿着 retryOnError 调用一些方法。 But if I want to do a
insertOrUpdate(List<Item> items)
this would be wasting a ton of time/resources.但是如果我想做一个
insertOrUpdate(List<Item> items)
这将浪费大量的时间/资源。 Ideally I would like to do something analogous to if (field == null) ? bindNull("field", field.class) : bind("field", myObj.field)
理想情况下,我想做一些类似于
if (field == null) ? bindNull("field", field.class) : bind("field", myObj.field)
事情if (field == null) ? bindNull("field", field.class) : bind("field", myObj.field)
if (field == null) ? bindNull("field", field.class) : bind("field", myObj.field)
somewhere somehow. if (field == null) ? bindNull("field", field.class) : bind("field", myObj.field)
某处。 If that is clearly off the table, I am still interested in figuring out a way to implement this is as efficiently as possible given what I'm working with.如果这显然不在桌面上,我仍然有兴趣找出一种方法来尽可能有效地实现这一点,因为我正在使用它。 Appreciate any feedback.
感谢任何反馈。
These are two questions:这是两个问题:
Statement
/ DatabaseClient
in a fluent style?Statement
/ DatabaseClient
? R2DBC and Spring Data R2DBC make null
handling explicit by requiring either binding a value to your Statement
or binding a null
. R2DBC和Spring数据R2DBC使
null
,要求一个值绑定到你的处理明确Statement
或绑定null
。 There's no method of accepting a potentially nullable argument.没有方法可以接受可能为空的参数。 There are two reasons for that:
有两个原因:
null
handling implicit.null
处理隐。 The implicit nature of null
is what causes the most bugs. null
的隐含性质是导致最多错误的原因。VARCHAR
, BIT
, INT
, …) and the actual value.VARCHAR
、 BIT
、 INT
等)和实际值的关联。 With calling bind(…)
with a value, a driver can derive the type information.bind(…)
,驱动程序可以派生类型信息。 When binding a null
value, the driver requires an additional type of information.null
值时,驱动程序需要其他类型的信息。 Otherwise, we cannot execute the query. That being said:话虽如此:
bindPotentiallyNull("auditId", entity.getTx().getId(), Integer.class)
bindPotentiallyNull("auditId", entity.getTx().getId(), Integer.class)
这样的 API We face a similar issue when talking about stored procedures, because stored procedures require additional details about in/out/in-out parameters.在谈论存储过程时,我们面临类似的问题,因为存储过程需要有关输入/输出/输入输出参数的其他详细信息。 We discussed potential wrapper types like
我们讨论了潜在的包装器类型,例如
Parameters.in(@Nullable T value, Class<? super T> valueType)
so these could be used as wrappers in所以这些可以用作包装器
bind("auditId", Parameters.in(entity.getTx().getId(), Integer.class))
Further details:更多细节:
Either setting a value or null can be done using the Parameter
class as shown below:可以使用
Parameter
类设置值或空值,如下所示:
import org.springframework.r2dbc.core.Parameter;
// rest of the code
.bind("customerId", Parameter.fromOrEmpty(o.getCustomerId(), UUID.class))
Earlier, it was SettableValue.fromOrEmpty
, which is not deprecated.早些时候,它是
SettableValue.fromOrEmpty
,它没有被弃用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.