Spring boot Spring Webflux+;JPA:JPA不支持反应式存储库

Spring boot Spring Webflux+;JPA:JPA不支持反应式存储库,spring-boot,spring-data-jpa,spring-webflux,Spring Boot,Spring Data Jpa,Spring Webflux,启动我的应用程序时出错JPA:JPA不支持反应式存储库。 我的Pom有以下依赖项,我使用的是SpringBoot2.0.5 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency&

启动我的应用程序时出错
JPA:JPA不支持反应式存储库。
我的Pom有以下依赖项,我使用的是
SpringBoot2.0.5

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
当我启动应用程序时,它会抛出错误:

org.springframework.dao.InvalidDataAccessApiUsageException: Reactive Repositories are not supported by JPA. Offending repository is com.example.demo.CustomerRepository!
    at org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.useRepositoryConfiguration(RepositoryConfigurationExtensionSupport.java:310) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport.getRepositoryConfigurations(RepositoryConfigurationExtensionSupport.java:103) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.data.repository.config.RepositoryConfigurationDelegate.registerRepositoriesIn(RepositoryConfigurationDelegate.java:126) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
    at org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport.registerBeanDefinitions(AbstractRepositoryConfigurationSourceSupport.java:60) ~[spring-boot-autoconfigure-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.lambda$loadBeanDefinitionsFromRegistrars$1(ConfigurationClassBeanDefinitionReader.java:358) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[na:1.8.0_144]
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsFromRegistrars(ConfigurationClassBeanDefinitionReader.java:357) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:145) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:117) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:328) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:233) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:271) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:91) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:694) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:532) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
    at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:61) ~[spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:780) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]

如果JPA不受支持,请告诉我应该使用什么,非常感谢您的帮助。

如果您想获得反应式异步/非阻塞的所有好处,您需要使整个堆栈异步/非阻塞。JDBC本质上确实是一个阻塞API,因此如果需要通过JDBC访问数据库,则无法构建完全反应/非阻塞的应用程序

但您仍然需要关系数据库,然后建议使用
rxjava2jdbc
,下面是使用RxJava和rxjavajdbc的完整示例


似乎目前SpringWebFlux支持Mongodb、Redis等nosql反应式,因此使用
SpringBootStarter数据Mongodb反应式
您可以尝试这个小型JPA反应式包装器,它不是真正的反应式包装器,而是在一个孤立的线程池上运行JDBC调用


即使您选择的数据库(H2)不支持非阻塞反应式查询,您仍然可以以阻塞方式获取数据,然后尽快将其转换为反应式类型,以利于上游组件

对于在JPA存储库上调用方法的阻塞性质,您无能为力。但是,您可以做的是,在收到非反应性类型后,立即将其转换为反应性类型(通量/单声道),以便从那时起可以反应性地处理结果


或者您可以使用另一个支持反应式模型的数据库,如Cassandra、MongoDB、Couchbase或Redis。

我不知道以前的支持情况,但从2019年6月9日起,您完全可以将WebFlux与JPA存储库一起使用

您的堆栈不必是完全反应的。我喜欢WebFlux,但需要一个关系数据库

我有:

  • 弹簧启动启动器数据redis reactive
  • 弹簧启动器webflux
  • spring引导启动器数据jpa
编辑:(仅供参考)代码在Kotlin中,但仍应在Java中工作

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = ["com.example.core.repositories"])
@EnableJpaAuditing
class PersistenceConfig
src/core/models/User

@Entity
@Table(name = "user")
class User(
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "user_id")
    var id: Long,

    @Column(name = "username")
    var username: String,

    @Column(name = "created_date", nullable = false, updatable = false)
    @CreatedDate
    @Temporal(TemporalType.TIMESTAMP)
    val createdDate: Date,

    @Column(name = "modified_date")
    @LastModifiedDate
    @Temporal(TemporalType.TIMESTAMP)
    val modifiedDate: Date
) : Serializable {

    /**
     * This constructor is not to be used. This is for hibernate,
     * which requires an empty constructor.
     */
    constructor() : this(1L, "", "", Date(), Date())

    companion object {
        private const val serialVersionUID = 2398467923L
    }

}
我得到了相同的
JPA:JPA不支持反应式存储库。
当我仍然从Spring数据查询返回mono对象时出错,如
mono
。但是,如果删除
Mono
包装器,它应该可以正常工作

src/core/repositories/UserRepository

@Repository
interface UserRepository: CrudRepository<User, Long> {

    fun findUserByUsername(username: String): User?

}
@存储库
接口用户存储库:CrudRepository{
fun findUserByUsername(用户名:字符串):用户?
}

为什么不使用R2DBC?它支持对关系数据库存储的反应式访问,并支持Postgresql、SQL server等


回答得好。然而,如果你的意思是这样的话,这个例子就没有用了。它只是将
crudepository
包装在
Flux
Mono
s中。Spring Data Redis不支持反应式存储库:@kj007您能解释一下“阻塞API”是什么意思吗?JDBC查询返回一个
ResultSet
和一个调用可以很快返回的AFAIK——它不需要实际获取整个结果集,尽管这是许多数据库的默认行为。我相信MySQL和PostgreSQL都有将结果集一次传输几个记录的方法,而不是一次传输所有记录。@Frans尽管速度很快,但在等待响应时仍然会阻塞线程。反应式是基于消息传递/回调的,因此您可以发出数据库请求,关闭线程,回调将在另一个线程中处理。比什么都不做更好的是,hope将有一个标准的jpa反应式。。。没过几年我就知道了。。。需要等待eclipseLocks,这是一个非常有前途的实现。似乎Hibernate团队正在做一些事情,如果最终在这里使用它,您将失去事务支持和更多。您的会话仅在调用findUserByUsername时才处于活动状态—不再是。所以不支持延迟加载关系等。它不支持manytone-,OnetoMany-,。。。关系
@Repository
interface UserRepository: CrudRepository<User, Long> {

    fun findUserByUsername(username: String): User?

}