Spring Webflux + JPA:JPA不支持Reactive Repositories

use*_*282 13 spring-data-jpa spring-boot spring-webflux

当我启动我的应用程序时,我收到错误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>
Run Code Online (Sandbox Code Playgroud)

这是我的存储库界面.

public interface CustomerRepository extends ReactiveCrudRepository {
}
Run Code Online (Sandbox Code Playgroud)

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

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]
Run Code Online (Sandbox Code Playgroud)

有人可以建议,如果JPA不受支持,那么我应该使用什么,任何帮助表示赞赏..

kj0*_*007 12

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

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

似乎目前Spring webflux支持Mongodb,Redis等nosql反应因此而不是JPA使用spring-boot-starter-data-mongodb-reactive.

  • @Frans 尽管速度很快,但它在等待响应时仍然会阻塞线程。响应式基于消息传递/回调,因此您可以发出数据库请求,关闭线程,然后回调将在另一个线程中处理。 (4认同)
  • 好答案。但是,如果这就是您的意思,那么该示例不使用 https://github.com/davidmoten/rxjava2-jdbc。它只是将 `CrudRepository` 包装在 `Flux` 和 `Mono` 中。 (2认同)

Cle*_*ent 8

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

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

我有:

  • spring-boot-starter-data-redis-反应
  • spring-boot-starter-webflux
  • spring-boot-starter-数据-jpa

编辑:(仅供参考)代码是用 Kotlin 编写的,但应该仍然可以在 Java 中使用。

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = ["com.example.core.repositories"])
@EnableJpaAuditing
class PersistenceConfig
Run Code Online (Sandbox Code Playgroud)

src/核心/模型/用户

@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
    }

}
Run Code Online (Sandbox Code Playgroud)

JPA: Reactive Repositories are not supported by JPA.当我仍然从 Spring Data 查询返回单对象时,我遇到了同样的错误,例如Mono<User>. 但是,如果去掉Mono包装纸,它应该可以正常工作。

src/core/repositories/UserRepository

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

    fun findUserByUsername(username: String): User?

}
Run Code Online (Sandbox Code Playgroud)

  • 通过使用它,您将失去事务支持等等。仅当您调用 findUserByUsername 时,您的会话才处于活动状态 - 不再有效。因此不支持延迟加载关系等。 (9认同)

Wes*_*Gun 5

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

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

  • 它不支持 ManyToOne-、OnetoMany-、... 关系 (8认同)