Spring Webflux + JPA:JPA 不支持 Reactive Repositories
Spring Webflux + JPA: Reactive Repositories are not supported by JPA
我在启动我的应用程序时遇到错误 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(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 访问数据库,则无法构建完全响应式/非阻塞的应用程序。
但是你仍然需要关系数据库,然后会推荐使用 rxjava2-jdbc
这里是使用 RxJava 和 RxJava 的完整示例 jdbc spring-webflux-async-jdbc-sample
似乎目前 Spring webflux 支持 Mongodb、Redis 等 nosql 反应性,因此使用 spring-boot-starter-data-mongodb-reactive
代替 JPA。
您可以试试这个小型 JPA 反应式包装器,它不是真正的反应式,但在独立的线程池上运行 JDBC 调用。
即使您选择的数据库 (H2) 不支持非阻塞响应式查询,您仍然可以以阻塞方式获取数据,然后尽快将其转换为响应式类型,以便上游组件受益.
对于在 JPA 存储库上调用方法的阻塞性质,您无能为力。但是,您可以做的是在收到后立即将非反应性类型转换为反应性类型 (Flux/Mono),以便您可以从那里反应性地处理结果。
或者您可以使用其他支持反应模型的数据库,例如 Cassandra、MongoDB、Couchbase 或 Redis。
我不知道以前的支持情况,但截至 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 数据查询(如 Mono<User>
)返回单声道对象时,我遇到了相同的 JPA: Reactive Repositories are not supported by JPA.
错误。但是,如果您删除 Mono
包装器,它应该可以正常工作。
src/core/repositories/UserRepository
@Repository
interface UserRepository: CrudRepository<User, Long> {
fun findUserByUsername(username: String): User?
}
你为什么不使用 R2DBC?它支持对关系数据库存储的反应式访问,并支持 Postgresql、SQL 服务器等。
我是这样解决的
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
@Repository
public interface ProductRepository extends ReactiveCrudRepository<Product, Long> {
@Query("SELECT * FROM product WHERE id = :id")
Flux<Product> findById(@Param("id") Long id);
}
我在启动我的应用程序时遇到错误 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(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 访问数据库,则无法构建完全响应式/非阻塞的应用程序。
但是你仍然需要关系数据库,然后会推荐使用 rxjava2-jdbc
这里是使用 RxJava 和 RxJava 的完整示例 jdbc spring-webflux-async-jdbc-sample
似乎目前 Spring webflux 支持 Mongodb、Redis 等 nosql 反应性,因此使用 spring-boot-starter-data-mongodb-reactive
代替 JPA。
您可以试试这个小型 JPA 反应式包装器,它不是真正的反应式,但在独立的线程池上运行 JDBC 调用。
即使您选择的数据库 (H2) 不支持非阻塞响应式查询,您仍然可以以阻塞方式获取数据,然后尽快将其转换为响应式类型,以便上游组件受益.
对于在 JPA 存储库上调用方法的阻塞性质,您无能为力。但是,您可以做的是在收到后立即将非反应性类型转换为反应性类型 (Flux/Mono),以便您可以从那里反应性地处理结果。
或者您可以使用其他支持反应模型的数据库,例如 Cassandra、MongoDB、Couchbase 或 Redis。
我不知道以前的支持情况,但截至 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 数据查询(如 Mono<User>
)返回单声道对象时,我遇到了相同的 JPA: Reactive Repositories are not supported by JPA.
错误。但是,如果您删除 Mono
包装器,它应该可以正常工作。
src/core/repositories/UserRepository
@Repository
interface UserRepository: CrudRepository<User, Long> {
fun findUserByUsername(username: String): User?
}
你为什么不使用 R2DBC?它支持对关系数据库存储的反应式访问,并支持 Postgresql、SQL 服务器等。
我是这样解决的
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
@Repository
public interface ProductRepository extends ReactiveCrudRepository<Product, Long> {
@Query("SELECT * FROM product WHERE id = :id")
Flux<Product> findById(@Param("id") Long id);
}