sourcecode

Spring Webflux + JPA :사후 대응 리포지토리는 JPA에서 지원되지 않습니다.

codebag 2023. 3. 19. 18:09
반응형

Spring Webflux + JPA :사후 대응 리포지토리는 JPA에서 지원되지 않습니다.

앱을 시작할 때 오류가 발생함JPA: Reactive Repositories are not supported by JPA.나의 폼은 아래의 의존관계를 가지고 있으며 나는 그것을 사용하고 있다.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가 지원되지 않을 경우 어떤 것을 사용해야 하는지 알려주시면 감사하겠습니다.

사후 대응, 비동기/비차단 기능을 모두 사용하려면 전체 스택을 비동기/비차단으로 만들어야 합니다.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.

이전 지원은 모르겠지만, 2019년 6월 9일부로 WebFlux를 JPA Repository와 함께 사용할 수 있습니다!

스택이 완전히 반응할 필요는 없습니다.WebFlux를 좋아하지만 관계형 데이터베이스가 필요합니다.

다음과 같은 것이 있습니다.

  • spring-boot-boot-data-redis-module
  • spring-boot-webflux
  • spring-boot-data-jpa

edit: (FYI) 코드는 Kotlin으로 되어 있지만 Java에서는 동작합니다.

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

src/core/모델/사용자

@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: Reactive Repositories are not supported by JPA.Spring Data 쿼리에서 모노 오브젝트를 반환하는 동안 오류가 발생했습니다.Mono<User>단, 를 삭제했을 경우Mono포장지, 잘 될 거야.

src/core/리포지토리/User Repository

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

    fun findUserByUsername(username: String): User?

}

왜 R2DBC를 안 쓰세요?관계형 데이터베이스 스토어에 대한 사후 대응 액세스를 지원하고 Postgresql, SQL 서버 등을 지원합니다.

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

선택한 데이터베이스(H2)가 논블로킹 대응 쿼리를 지원하지 않더라도 업스트림 구성 요소의 이점을 위해 가능한 한 빨리 블로킹 방식으로 데이터를 가져온 다음 대응 유형으로 변환할 수 있습니다.

JPA 저장소에서 메서드를 호출하는 차단 기능에 대해서는 아무것도 할 수 없습니다.다만, 비반응 타입을 수신하는 즉시 반응 타입(Flux/Mono)으로 변환하는 것으로, 그 후의 결과에 대응할 수 있습니다.

또는 Cassandra, MongoDB, Couchbase 또는 Redis와 같은 반응형 모델을 지원하는 다른 데이터베이스를 사용할 수 있습니다.

나는 이렇게 풀었다.

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 리액티브래퍼를 사용해 볼 수 있습니다.실제로 리액티브하지 않지만 분리된 스레드 풀에서 JDBC 콜을 실행합니다.

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

블로킹 API를 사용할 계획이라면 SpringMVC를 간단히 사용할 수 있습니다.이러한 테크놀로지는, 이 메뉴얼에 기재되어 있는 바와 같이, 이러한 테크놀로지에의 대처에 최적이기 때문입니다.

매뉴얼에서

블로킹 지속성 API(JPA, JDBC) 또는 네트워킹 API를 사용하는 경우 Spring MVC는 적어도 공통 아키텍처에 가장 적합한 선택입니다.Reactor와 RxJava 모두 개별 스레드로 블로킹콜을 실행하는 것은 기술적으로 실현 가능하지만 비블로킹 웹 스택을 최대한 활용할 수는 없습니다.

그렇지 않으면 rxjava2 또는 Reactor를 사용하여 차단 API를 처리할 수 있습니다. 예를 들어git 허브 프로젝트


PS: 늦은 알지만, 다른 관심 있는 분들을 위해서입니다.

언급URL : https://stackoverflow.com/questions/52480271/spring-webflux-jpa-reactive-repositories-are-not-supported-by-jpa

반응형