繁体   English   中英

如何使用 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 (reactive) 在 R2dbc (java) 中构建有效的查询。 使用 R2dbc 提供的 DatabaseClient 对象(或一个 Connection 对象),似乎我只能调用这两种方法之一的不同变体: bind(Object field, Object value)bindNull(Object field, Class<?> type) 如果我有一个架构和一个对应的 Java 类,有多个可为空的字段,我应该如何[有点]有效地处理这个问题?

举个例子:

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 。 问题是,如果我确实调用了绑定,则该值不能为空。 如果我调用 bindNull,则该值必须为 null。 我如何能够根据我的值是否实际上为空来调用一个或另一个? 我已经知道我可以为每个场景创建一堆方法或沿着 retryOnError 调用一些方法。 但是如果我想做一个insertOrUpdate(List<Item> items)这将浪费大量的时间/资源。 理想情况下,我想做一些类似于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)某处。 如果这显然不在桌面上,我仍然有兴趣找出一种方法来尽可能有效地实现这一点,因为我正在使用它。 感谢任何反馈。

这是两个问题:

  1. 如何以流畅的方式将可能为空的值绑定到Statement / DatabaseClient
  2. 如何让数据库解决剩下的问题?

R2DBC和Spring数据R2DBC使null ,要求一个值绑定到你的处理明确Statement或绑定null 没有方法可以接受可能为空的参数。 有两个原因:

  1. 您应该处理可空性以明确那里发生的事情。 这是一个很好的习惯来处理,而不是把空的值null处理隐。 null的隐含性质是导致最多错误的原因。
  2. 数据库要求显式。 带有占位符的参数化语句包含在两个块的执行端:SQL 语句本身和参数绑定(描述符)。 参数描述符需要与占位符、类型信息( VARCHARBITINT等)和实际值的关联。 通过使用值调用bind(…) ,驱动程序可以派生类型信息。 绑定null值时,驱动程序需要其他类型的信息。 否则,我们无法执行查询。

话虽如此:

  1. 没有像bindPotentiallyNull("auditId", entity.getTx().getId(), Integer.class)这样的 API
  2. 您不能在 SQL 查询中执行任何操作,因为绑定参数信息是由辅助方法提供的。

在谈论存储过程时,我们面临类似的问题,因为存储过程需要有关输入/输出/输入输出参数的其他详细信息。 我们讨论了潜在的包装器类型,例如

Parameters.in(@Nullable T value, Class<? super T> valueType)

所以这些可以用作包装器

bind("auditId", Parameters.in(entity.getTx().getId(), Integer.class))

更多细节:

可以使用Parameter类设置值或空值,如下所示:

import org.springframework.r2dbc.core.Parameter;

// rest of the code

.bind("customerId", Parameter.fromOrEmpty(o.getCustomerId(), UUID.class))

早些时候,它是SettableValue.fromOrEmpty ,它没有被弃用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM