【问题标题】:Spring Webflux + JPA: Reactive Repositories are not supported by JPASpring Webflux + JPA:JPA 不支持反应式存储库
【发布时间】:2019-02-28 00:29:50
【问题描述】:

当我启动我的应用程序时出现错误JPA: Reactive Repositories are not supported by JPA. 我的 Pom 有以下依赖项,我正在使用 Spring Boot 2.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>

这是我的存储库界面。

public interface CustomerRepository extends ReactiveCrudRepository {
}

当我启动我的应用程序时,它会抛出错误:

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,有人可以告诉我应该使用什么,感谢任何帮助..

【问题讨论】:

    标签: spring-boot spring-data-jpa spring-webflux


    【解决方案1】:

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

    但是你仍然需要关系数据库,那么建议使用rxjava2-jdbc,这里是使用 RxJava 和 RxJava jdbc spring-webflux-async-jdbc-sample的完整示例

    目前似乎 Spring webflux 支持 Mongodb、Redis 等 nosql 反应式,因此使用 spring-boot-starter-data-mongodb-reactive 代替 JPA。

    【讨论】:

    • 好答案。但是,如果这就是您的意思,那么该示例不使用 github.com/davidmoten/rxjava2-jdbc。它只是将CrudRepository 包装在FluxMonos 中。
    • Spring Data Redis 不支持响应式存储库:jira.spring.io/browse/DATAREDIS-796
    • @kj007 你能解释一下“阻塞 API”是什么意思吗? JDBC 查询返回 ResultSet 和 AFAIK,该调用可以很快返回——它不需要实际获取整个结果集,尽管这是许多数据库的默认行为。我相信 MySQL 和 PostgreSQL 都有方法一次流式传输结果集几条记录,而不是一次全部记录。
    • @Frans 尽管速度很快,但它在等待响应时仍会阻塞线程。响应式基于消息/回调,因此您可以发出数据库请求,关闭线程,回调将在另一个线程中处理。
    • 我同意@heez 的观点,因为spring-webflux-async-jdbc-sample 并没有真正产生正确的效果。如果查询等到检索到完整的结果集(关系数据库的正常行为),然后再将行输入到 Flux 中,那么您将无法获得与响应式 NoSQL DB 相同的好处。以块的形式(分页)抓取数据可能会使 RDB 查询的行为更具反应性。
    【解决方案2】:

    您可以尝试这个小型 JPA 反应式包装器,它不是真正的反应式,而是在隔离的 ThreadPool 上运行 JDBC 调用。

    https://github.com/IBM/reactive-components

    【讨论】:

    • 比没有好,希望会有一些标准来让 jpa 反应...而不是几年前我的事情...需要等待日食
    • 锁定是一个非常有前途的实现。
    • Hibernate 团队似乎在做某事github.com/hibernate/hibernate-rx
    【解决方案3】:

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

    对于在 JPA 存储库上调用方法的阻塞性质,您无能为力。但是,您可以做的是,在收到非响应式类型后立即将其转换为响应式类型(Flux/Mono),以便您可以从那里响应式处理结果。

    或者您可以使用其他支持响应式模型的数据库,例如 Cassandra、MongoDB、Couchbase 或 Redis。

    【讨论】:

      【解决方案4】:

      我不知道以前的支持,但截至 2019 年 6 月 9 日,您绝对可以将 WebFlux 与 JPA 存储库一起使用!

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

      我有:

      • spring-boot-starter-data-redis-reactive
      • spring-boot-starter-webflux
      • spring-boot-starter-data-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
          }
      
      }
      

      当我仍然从 Spring Data 查询(如 Mono&lt;User&gt;)返回单声道对象时,我遇到了相同的 JPA: Reactive Repositories are not supported by JPA. 错误。但是,如果您删除 Mono 包装器,它应该可以正常工作。

      src/core/repositories/UserRepository

      @Repository
      interface UserRepository: CrudRepository<User, Long> {
      
          fun findUserByUsername(username: String): User?
      
      }
      

      【讨论】:

      • 使用它,您将失去交易支持等等。您的会话仅在您调用 findUserByUsername 时才处于活动状态 - 不再是。所以不支持延迟加载关系等。
      【解决方案5】:

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

      https://spring.io/projects/spring-data-r2dbc

      【讨论】:

      • 不支持ManyToOne-、OnetoMany-、...关系
      猜你喜欢
      • 2019-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-08
      • 2017-12-27
      • 2020-04-05
      • 2021-11-18
      • 2018-06-24
      相关资源
      最近更新 更多