带有 JPA 和 R2DBC 的 Spring Boot 2.4 混合项目无法启动
Posted
技术标签:
【中文标题】带有 JPA 和 R2DBC 的 Spring Boot 2.4 混合项目无法启动【英文标题】:Spring Boot 2.4 mixed project with JPA and R2DBC doesn't start 【发布时间】:2021-03-04 02:39:19 【问题描述】:我正在处理现有的 Spring Boot 2.4 项目,并尝试将 Webflux 和 R2DBC 引入现有的基于 JPA 的应用程序中。
我能够引入 Webflux 依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
没有任何问题,我的应用程序启动并正常运行,能够使用 Flux/Mono 执行一些测试,一切都很好。
然而,为了获得完全的响应性,我需要一直深入到持久层,即还引入 R2DBC 依赖项(对于 postgres)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-postgresql</artifactId>
<version>0.8.6.RELEASE</version>
</dependency>
我的配置类如下:
@Configuration
@EnableR2dbcRepositories(
repositoryBaseClass = ReactiveCrudRepository.class
)
public class R2DBCConfiguration extends AbstractR2dbcConfiguration
@Bean
@Qualifier("rxConnectionFactory")
@Override
public ConnectionFactory connectionFactory()
return new PostgresqlConnectionFactory(
PostgresqlConnectionConfiguration
.builder()
.username("user")
.password("password")
.host("localhost")
.port(5432)
.database("my_db")
.build()
);
由于这种依赖关系,我的项目无法启动,始终给出相同的异常:
Caused by: java.lang.IllegalStateException: Cannot apply reactive transaction to non-reactive return type: interface java.util.List
at org.springframework.transaction.interceptor.TransactionAspectSupport.lambda$invokeWithinTransaction$0(TransactionAspectSupport.java:351)
at java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:324)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:346)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:134)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
at com.mycompany.myapplication.service.SettingsServiceImpl$$EnhancerBySpringCGLIB$$5198d258.findAll(<generated>)
at com.mycompany.myapplication.service.RuntimeSettingsServiceImpl.populateMap(RuntimeSettingsServiceImpl.java:96)
at com.mycompany.myapplication.service.RuntimeSettingsServiceImpl.init(RuntimeSettingsServiceImpl.java:65)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157)
... 109 common frames omitted
我无法理解为什么会发生这种情况 - 我们确实为我们的 DAO 使用了传统的 SimpleJpaRepository 实现/它们都没有扩展 ReactiveCrudRepository,因此从应用程序的角度来看,不应将其“视为”响应式存储。
无论如何,我想知道其他人是否遇到过类似的情况以及可能的解决方法/修复。
【问题讨论】:
那么 JPA 存储库如何知道要使用什么连接?您的异常指向SettingsServiceImpl
,它说它正在使用反应式 jdbc 连接来执行其事务。我没有为您提供任何解决方案,但没有人能够帮助您,因为您没有生成任何代码来重现该问题。所有发布的代码都有效,发布的代码不起作用,或者有足够的代码来重现问题。投票结束。
【参考方案1】:
查看我对this question的回复,我还提供了a working example。
顺便说一句,我认为在示例应用程序中混合阻塞 JPA API 和非阻塞 R2dbc API 不是一个好的选择。
【讨论】:
谢谢!我的预期设计是为某些用例单独使用反应式 API,这些用例都是只读操作。 你能解释一下为什么它不是一个很好的选择吗?我还在使用 JDBC 和托盘来添加 R2DBC 支持的项目。我想使用 JPA 来编辑/插入记录,使用 R2DBC 来返回 Flux 而不是 List。是性能、内存/cpu 消耗还是其他问题?以上是关于带有 JPA 和 R2DBC 的 Spring Boot 2.4 混合项目无法启动的主要内容,如果未能解决你的问题,请参考以下文章
无法使用带有 Spring Data 反应式存储库的 Oracle R2DBC 驱动程序执行任何查询
如何在Jpa中使用所选实体创建行,RestController Spring Boot
如何在 R2DBC 和 Spring WebFlux 中加入多个表?