我必须重新实现一些后端服务,主要要求之一是使整个流程具有反应性。以前,服务使用 PostgreSQL 休眠,因此上述连接是由框架提供的。
由于我必须保留原始数据库并更改服务实现,因此我必须使用 r2dbc-postgresql。我找不到关于这个主题的任何资源,但我最好的猜测是做一些类似于我会用 JDBC 做的事情,并在我的实体之间引入一些新的连接表。
postgresql project-reactor spring-webflux spring-data-r2dbc r2dbc
我们在生产中使用spring-data-r2dbc:1.3.2
并dev.miku:r2dbc-mysql:0.8.2.RELEASE
遇到了一个奇怪的问题。
我们不明白根本原因是什么,也不知道它是否是可恢复的,或者是否真的会产生不可预测的结果(如日志所示)。
我们定期看到错误日志如下:
我们每天都会看到它几次,这让我们感到紧张,因为它明确指出:这可能是一个导致不可预测结果的错误
我们在日志中没有得到任何附加信息。
几个问题:
我使用Vert.x工具包来创建反应式应用程序,支持MySQL和Postgres等关系数据库.我知道Spring为像Cassandra和Mongo这样的NoSQL DB提供了反应支持,但是他们是否愿意为关系数据库提供相同的支持?
我正在学习 Spring WebFlux。
我的实体是这样的:
@Table("users")
public class User {
@Id
private Integer id;
private String name;
private int age;
private double salary;
}
Run Code Online (Sandbox Code Playgroud)
我有一个存储库(R2 使用 H2 数据库),如下所示:
public interface UserRepository extends ReactiveCrudRepository<User,Integer> {
}
Run Code Online (Sandbox Code Playgroud)
我的控制器是:
@Autowired
private UserRepository userRepository;
private static List<User> userList = new ArrayList<>();
@PostConstruct
public void initializeStockObjects() {
User stock1 = new User(11, "aaaa", 123, 123);
User stock2 = new User(12, "bbb", 123, 123);
User stock3 = new User(13, "ccc", 123, 123);
userList.add(stock1);
userList.add(stock2);
userList.add(stock3);
}
@RequestMapping(value …
Run Code Online (Sandbox Code Playgroud) 我正在使用r2dbc
,r2dbc-h2
并且是实验性的spring-boot-starter-data-r2dbc
implementation 'org.springframework.boot.experimental:spring-boot-starter-data-r2dbc:0.1.0.M1'
implementation 'org.springframework.data:spring-data-r2dbc:1.0.0.RELEASE' // starter-data provides old version
implementation 'io.r2dbc:r2dbc-h2:0.8.0.RELEASE'
implementation 'io.r2dbc:r2dbc-pool:0.8.0.RELEASE'
Run Code Online (Sandbox Code Playgroud)
我创建了反应式存储库
public interface IJsonComparisonRepository extends ReactiveCrudRepository<JsonComparisonResult, String> {}
Run Code Online (Sandbox Code Playgroud)
还添加了一个自定义脚本,在启动时在 H2 中创建一个表
@SpringBootApplication
public class JsonComparisonApplication {
public static void main(String[] args) {
SpringApplication.run(JsonComparisonApplication.class, args);
}
@Bean
public CommandLineRunner startup(DatabaseClient client) {
return (args) -> client
.execute(() -> {
var resource = new ClassPathResource("ddl/script.sql");
try (var is = new InputStreamReader(resource.getInputStream())) {
return FileCopyUtils.copyToString(is);
} catch (IOException e) {
throw new RuntimeException(e);
} …
Run Code Online (Sandbox Code Playgroud) 在java反应器中,r2dbc。我有两个表 A、B。我也为它们定义了存储库。如何获取由 A 连接 B 组成的数据?
我只提出了以下方法:从 A 调用 databaseClient.select,因此在循环中从 B 调用 select。
但我想要更有效和反应性的方式。怎么做?
在Spring Data R2DBC 中,我可以使用
logging.level.org.springframework.data.r2dbc=DEBUG
Run Code Online (Sandbox Code Playgroud)
在application.properties
.
但是,这不会记录绑定为查询参数的实际值。
如何在 Spring Data R2DBC 中记录查询参数的实际值?
我正在尝试利用 H2 进行测试并在 中有以下配置src/test/resources/application.yaml
:
spring:
r2dbc:
url: r2dbc:h2:file://testdb
Run Code Online (Sandbox Code Playgroud)
我有一个带有注释的空测试,@SpringBootTest
但是当我运行它时,出现以下错误:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.r2dbc.pool.ConnectionPool]: Factory method 'connectionFactory' threw exception; nested exception is java.lang.IllegalStateException: Unable to create a ConnectionFactory for 'ConnectionFactoryOptions{options={driver=h2, protocol=file, host=testdb}}'. Available drivers: [ pool, postgresql, h2 ]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651)
... 131 common frames omitted
Caused by: java.lang.IllegalStateException: Unable to create a ConnectionFactory for 'ConnectionFactoryOptions{options={driver=h2, protocol=file, host=testdb}}'. Available drivers: [ pool, postgresql, h2 ]
at io.r2dbc.spi.ConnectionFactories.get(ConnectionFactories.java:145)
at org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBuilder.build(ConnectionFactoryBuilder.java:125)
at org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryConfigurations.createConnectionFactory(ConnectionFactoryConfigurations.java:56)
at …
Run Code Online (Sandbox Code Playgroud) 我需要批量将多行插入到一个表中。在 DatabaseClient 中,我发现 insert() 语句和 using(Publisher objectToInsert) 方法有多个对象作为参数。但它是否会将它们批量插入?另一个可能的解决方案是connection.createBatch(),但它有一个缺点:我无法在那里传递我的实体对象,并且无法从实体生成sql查询。
那么,是否可以在r2dbc中创建批量插入?
“...在反应式执行的情况下,如果支持实现是阻塞的,Micronaut Data 将使用配置的 I/O 线程池在不同的线程上调度查询执行。
如果支持实现在驱动程序级别本机支持反应类型,则不使用 I/O 线程池,而是假定驱动程序将以非阻塞方式处理查询......”
我的直接问题:访问关系数据库(例如 PostGres R2DBC 驱动程序)抛出 R2DBC Micronaut Data 是否会依赖 R2DBC 驱动程序以非阻塞方式处理并且更具可扩展性?
假设我的微服务公开了一个基于 ReactiveX 的 Reactive 端点并且必须访问一个阻塞数据源 throw Micronaut Data JDBC(例如,生产版本中还没有 Oracle R2DBC),从上面可以清楚地看出它“将使用配置我/O 线程池”,同时访问数据。我是否完全失去了响应式端点的好处?
这是我与 Micronaut 合作的第一个项目,我有几个采用 Reactive 方法的项目。我远不是反应式最佳实践方面的专家,但我记得我已经阅读了几篇博客:如果您有阻塞源,请避免使用反应式堆栈。我还记得读到过,将非阻塞与阻塞设计混合在一起可能会产生更糟糕的结果,这主要是因为 Eventloop(例如 Netty)的设计方式。由于我将 Micronaut 与 ReactiveX 和关系数据库一起使用,某些情况下使用 R2DBC,而其他情况下使用 JDBC,我将感谢对我的疑问的任何评论。
r2dbc ×10
h2 ×3
java ×3
spring ×3
spring-boot ×3
spring-data ×2
micronaut ×1
netty ×1
postgresql ×1
r2dbc-mysql ×1
reactive ×1
reactivex ×1