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