WebFlux 기반에선 jpa는 권장하지 않는대..

아무튼 간에·2023년 1월 30일
0

Netty

목록 보기
4/4

개발환경

OS: Windows 11
IDE: IntellJ IDEA 2022.2.4 (Ultimate Edition)
Java: 1.8

Framework: Springframework.boot version: 2.4.3


WebFlux라는 거 자체도 힘들었는데 왜... 쉬운게 하나도 없는거니

JPA는 기본적으로 비동기를 제공하지 않는다.
Webflux 모듈은 기본적으로 비동기 non-blocking 방식을 지원하는데 JPA를 사용하면 Database 부분에서 block되고, 그동안 thread가 기다리게 된다.
참고 - R2DBC를 사용해보자 (1) - 왜 사용할까?

그래서 울며 겨자먹기로 R2D2를 사용함.

고생 깨나 함. 시행착오를 겪는 과정이기 때문에 틀린 내용이 있을 수 있음.


build.gradle

implementation "org.springframework.boot:spring-boot-starter-data-r2dbc"
implementation 'com.github.jasync-sql:jasync-r2dbc-mysql:2.1.7'
implementation group: 'javax.persistence', name: 'javax.persistence-api', version: '2.2'

application.yml

spring:
	r2dbc:
    url: r2dbc:pool:mysql://127.0.0.1:3306/fruit
    username: armton
    password: 비밀번호~

FruitEntity

import lombok.*;
import org.springframework.data.annotation.*;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;

import javax.persistence.*;

@Table(name = "fruit_entity")	// R2D2에선 인식 X
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
@Getter
@Setter
public class FruitEntity {

    @Id
    @Column(name = "NAME")
    private String name;

    @Column(name = "TYPE")
    private String type;

    @Column(name = "CREATE_DATE")
    @CreatedDate
    private String createDate;

    @Column(name = "UPDATE_DATE")
    @LastModifiedDate
    private String updateDate;

    @Transient
    private String errorCode;

    @Transient
    private String errorMessage;

}

JPA와 비슷한듯 뭔가 다른 엔티티 구성

  • ★★★ @Id, @Transient 어노테이션은 org.springframework.data.annotation★★★
  • @Table에 name으로 테이블 명을 지정해줘도 반영이 안 됨. 카멜표기법 클래스명으로만 인식함.
    → ex) 실제 테이블명이 fruit_entity인 경우엔 클래스명을 FruitEntity으로 생성해야만 함.
  • @CreatedDate 딱히 안 먹힘

** 참고로 지금 나는 여기서 @IdString으로 선언했다. R2D2는 Update 시 Long형의 Id만 인지함. 이렇게 String로 하면 Persistable을 구현하고 isNew()를 재정의해도 반영되지 않음.

FruitRepository

import com.armton.r2d2.model.FruitEntity;
import org.springframework.data.r2dbc.repository.R2dbcRepository;
import reactor.core.publisher.Mono;

public interface FruitRepository extends R2dbcRepository<FruitEntity, String> {

    // 커스텀 메소드 생성 예시
    // Mono나 Flux 타입으로 받아야 함.
    Mono<FruitEntity> findByName(String name);
    Mono<Void> deleteByName(String name);

}
  • extends를 처음에 ReactiveCrudRepository를 받았는데 이걸로 하면 bean 생성을 못 함.
    에러 내용
    ~Repository bean not found
    → application클래스에 @EnableR2dbcRepositories("com.armton.r2d2.repository") 이걸 달아줬는데도 못 찾음 → R2dbcRepository로 바꿔줬더니 됨.

Service

@Service RegisterService.java

private final FruitClient fruitClient;

public Mono<String> registerFruit(Register register) throws CustomException {
    return fruitClient.insertFruit(
					FruitEntity.builder()
                    .name(register.getName())
                    .type(register.getType())
                    .build()).log()
        .flatMap(check -> {
            if(check){
                return Mono.just(OK);
            }else{
                throw new CustomException(FAILED_INSERT_FRUIT);
            }
        });
}

@Service FruitClient.java

private final FruitRepository fruitRepository;

@Autowired
public FruitClient(FruitRepository fruitRepository) {
	this.fruitRepository = fruitRepository;
}

public Mono<Boolean> insertFruit(FruitEntity fruitEntity) {
    try {
        fruitRepository.save(fruitEntity).subscribe();
        return Mono.just(true);
    }catch (Exception e){
        e.printStackTrace();
        return Mono.just(false);
    }
}
profile
armton garnet

0개의 댓글