Spring

Spring 데이터로 R2DBC 살펴보기

기록만이살길 2023. 1. 17. 03:06
반응형

1. 소개

R2DBC (Reactive Relational Database Connectivity)는 Spring One Platform 2018에서 Pivotal이 발표한 노력입니다. SQL 데이터베이스에 대한 반응형 API를 만들려고 합니다.

즉, 이러한 노력은 완전한 비차단 드라이버를 사용하여 데이터베이스 연결을 생성합니다.

이 예제에서는 Spring Data R2BDC를 사용하는 애플리케이션의 예를 살펴보겠습니다. 더 낮은 수준의 R2DBC API에 대한 사용방법(예제)는 이전 기사 를 참조하십시오 .

2. 첫 번째 Spring Data R2DBC 프로젝트

우선, R2DBC 프로젝트는 매우 최근의 프로젝트입니다. 현재  PostGres, MSSQL 및 H2에만 R2DBC 드라이버가 있습니다. 또한 모든 Spring Boot 기능 을 사용할 수 없습니다. 따라서 수동으로 추가해야 하는 몇 가지 단계가 있습니다. 그러나 Spring Data 와 같은 프로젝트를 활용 하여 도움을 받을 수 있습니다.

먼저 Maven 프로젝트를 생성합니다. 이 시점에서 R2DBC에는 몇 가지 의존성 문제가 있으므로 pom.xml 이 평소보다 커집니다.

이 기사의 범위에서는 H2 를 데이터베이스로 사용하고 애플리케이션을 위한 반응형 CRUD 기능을 생성합니다.

생성된 프로젝트의 pom.xml 을 열고 적절한 의존성과 일부 초기 릴리스 Spring 리포지토리를 추가해 보겠습니다.

<dependencies>
     <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-r2dbc</artifactId>
        <version>1.0.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>io.r2dbc</groupId>
        <artifactId>r2dbc-h2</artifactId>
        <version>0.8.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>1.4.199</version>
    </dependency>
</dependencies>

기타 필요한 아티팩트에는 Lombok,  Spring WebFlux 및 프로젝트 의존성 을 완료하는 몇 가지 기타 항목이 포함됩니다 .

3. 연결 Factory

데이터베이스로 작업할 때 연결 팩토리가 필요합니다. 물론 R2DBC에도 같은 것이 필요합니다.

이제 인스턴스에 연결하기 위한 세부 정보를 추가합니다.

@Configuration
@EnableR2dbcRepositories
class R2DBCConfiguration extends AbstractR2dbcConfiguration {
    @Bean
    public H2ConnectionFactory connectionFactory() {
        return new H2ConnectionFactory(
            H2ConnectionConfiguration.builder()
              .url("mem:testdb;DB_CLOSE_DELAY=-1;")
              .username("sa")
              .build()
        );
    }
}

위의 코드에서 가장 먼저 눈에 띄는 것은 @EnableR2dbcRepositories 입니다. Spring Data 기능을 사용하려면 이 어노테이션이 필요합니다. 또한 AbstractR2dbcConfiguration 은 나중에 필요한 많은 bean을 제공하므로 확장하고  있습니다.

4. 첫 번째 R2DBC 애플리케이션

다음 단계는 저장소를 만드는 것입니다.

interface PlayerRepository extends ReactiveCrudRepository<Player, Integer> {}

ReactiveCrudRepository 인터페이스 는 매우 유용합니다. 예를 들어 기본 CRUD 기능을 제공합니다.

마지막으로 모델 클래스를 정의합니다. 상용구 코드를 피하기 위해 Lombok을 사용합니다.

@Data
@NoArgsConstructor
@AllArgsConstructor
class Player {
    @Id
    Integer id;
    String name;
    Integer age;
}

5. 테스트

코드 를 테스트 할 시간 입니다. 이제 몇 가지 테스트 사례를 만들어 보겠습니다.

@Test
public void whenDeleteAll_then0IsExpected() {
    playerRepository.deleteAll()
      .as(StepVerifier::create)
      .expectNextCount(0)
      .verifyComplete();
}

@Test
public void whenInsert6_then6AreExpected() {
    insertPlayers();
    playerRepository.findAll()
      .as(StepVerifier::create)
      .expectNextCount(6)
      .verifyComplete();
}

6. Custom 검색어

사용자 정의 쿼리를 생성할 수도 있습니다 . 추가하려면 PlayerRepository 를 변경해야 합니다 .

@Query("select id, name, age from player where name = $1")
Flux<Player> findAllByName(String name);

@Query("select * from player where age = $1")
Flux<Player> findByAge(int age);

기존 테스트 외에도 최근 업데이트된 리포지토리에 테스트를 추가합니다.

@Test
public void whenSearchForCR7_then1IsExpected() {
    insertPlayers();
    playerRepository.findAllByName("CR7")
      .as(StepVerifier::create)
      .expectNextCount(1)
      .verifyComplete();
}

@Test
public void whenSearchFor32YearsOld_then2AreExpected() {
    insertPlayers();
    playerRepository.findByAge(32)
      .as(StepVerifier::create)
      .expectNextCount(2)
      .verifyComplete();
}

private void insertPlayers() {
    List<Player> players = Arrays.asList(
        new Player(1, "Kaka", 37),
        new Player(2, "Messi", 32),
        new Player(3, "Mbappé", 20),
        new Player(4, "CR7", 34),
        new Player(5, "Lewandowski", 30),
        new Player(6, "Cavani", 32)
    );
    playerRepository.saveAll(players).subscribe();
}

7. 배치

R2DBC의 또 다른 기능은 배치를 생성하는 것입니다. 배치는 개별 작업보다 더 잘 수행되므로 여러 SQL 문을 실행할 때 유용합니다.

Batch 를 만들려면 연결  개체 가 필요 합니다.

Batch batch = connection.createBatch();

애플리케이션이 Batch 인스턴스를 생성한 후 원하는 만큼 SQL 문을 추가할 수 있습니다. 이를 실행하기 위해 execute()  메서드를 호출합니다. 일괄 처리의 결과는 각 문에 대한 결과 개체를 반환하는 게시자 입니다.

이제 코드로 이동하여 Batch 를 만드는 방법을 살펴보겠습니다 .

@Test
public void whenBatchHas2Operations_then2AreExpected() {
    Mono.from(factory.create())
      .flatMapMany(connection -> Flux.from(connection
        .createBatch()
        .add("select * from player")
        .add("select * from player")
        .execute()))
      .as(StepVerifier::create)
      .expectNextCount(2)
      .verifyComplete();
}

8. 결론

요약하면 R2DBC는 아직 초기 단계입니다. SQL 데이터베이스에 대한 반응형 API를 정의하는 SPI를 생성하려는 시도입니다. Spring WebFlux 와 함께 사용하면 R2DBC를 사용하여 위쪽에서 데이터베이스까지 데이터를 비동기식으로 처리하는 애플리케이션을 작성할 수 있습니다.

항상 그렇듯이 코드는 GitHub 에서 사용할 수 있습니다 .

Persistence footer banner
참고
  • https://docs.spring.io/spring-framework/docs/current/reference/html
  • https://www.baeldung.com/spring-data-r2dbc
반응형