모노가 비어 있는 경우에만 작업을 수행하고 비어 있지 않은 경우에는 오류를 발생시키는 방법
Spring WebFlux를 사용하기 위해 프로젝트를 변환하려고 하는데 기본적인 비즈니스 로직을 사용하는 데 문제가 발생하고 있습니다.레코드 검색/유지를 담당하는 저장소 계층과 애플리케이션의 비즈니스 규칙을 담당하는 서비스 계층이 있습니다.서비스 계층에서 수행할 작업은 지정된 사용자 이름에 대한 사용자가 이미 있는지 확인하는 것입니다.그렇다면 오류로 대응하고 싶습니다.그렇지 않으면 삽입을 허용하고 싶습니다.
저장소 계층에서 사용자 이름으로 사용자를 찾고 찾지 못하면 빈 Mono를 반환하는 메서드를 호출합니다.이것은 예상대로 작동하지만, 저는 flatMap과 (defaultIfEmpty와 swithIfEmpty)의 다양한 조합을 시도했지만 컴파일/빌드를 할 수 없습니다.
public Mono<User> insertUser(User user) {
return userRepository.findByUsername(user.username())
.flatMap(__ -> Mono.error(new DuplicateResourceException("User already exists with username [" + user.username() + "]")))
.switchIfEmpty(userRepository.insertUser(user));
}
제가 받고 있는 오류는Mono<Object> cannot be converted to Mono<User>
그래서swithIfEmpty
적절한 유형을 반영하지 못하는 것 같고 캐스팅도 제대로 되지 않는 것 같습니다.
추가 테스트 후 동료 개발자들의 반응을 고려하여 다음 솔루션에 도달했습니다.
public Mono<User> insertUser(User user) {
return userRepository.findByUsername(user.username())
.flatMap(__ -> Mono.error(new DuplicateResourceException("User already exists with username [" + user.username() + "]")))
.switchIfEmpty(Mono.defer(() -> userRepository.insertUser(user)))
.cast(User.class);
}
토마스가 말했듯이, 컴파일러는 혼란스러워하고 있었습니다.제 추측은 왜냐하면flatMap
오류가 있는 모노를 반환하고 있었습니다.switchIfEmpty
사용자가 있는 모노를 반환하여 개체가 있는 모노로 돌아갑니다(따라서 추가)..cast
컴파일할 연산자).
다른 추가 사항은 다음을 추가하는 것이었습니다.Mono.defer
에서switchMap
그렇지 않으면,switchIfEmpty
항상 총을 쏘고 있었습니다.
저는 여전히 다른 제안/대안에 대해 열려 있습니다(이것이 상당히 일반적인 필요/패턴인 것처럼 보이기 때문입니다).
형식 매개 변수가 있는 추상 클래스를 사용하고 있습니다.E
그래서 사용할 수 없었습니다..cast(E.class)
우리의 해결책은
private Mono<E> checkIfStatementExists(E statement) {
return this.statementService.getByStatementRequestId(statement.getStatementRequestId())
.flatMap(sr -> Mono.<E>error(new ValidationException("Statement already exists for this request!")))
.switchIfEmpty(Mono.just(statement));
}
이 문제는 다음 주에 동료들과 상의해야 할 것 같습니다.
편집. 동료들과 상의를 해보았는데 업데이트된 코드는 위와 같습니다.
이 컴파일러 오류가 발생하는 이유는 다음과 같습니다.
flatmap
완료된 내용을 가져옵니다.Mono
추론할 수 있는 모든 유형으로 변환하려고 합니다. Mono.error
유형을 포함하며 이 유형은Object
.
한 가지 방법은 대신 논리를 플랫 맵으로 이동하는 것일 수 있습니다.
// This is just example code using strings instead of repos
public Mono<String> insertUser(String user) {
return Mono.just(user)
// Here we map/convert instead based on logic
.flatMap(__ -> {
if (__.isEmpty())
return Mono.error(new IllegalArgumentException("User already exists with username [" + user + "]"));
return Mono.just(user);
}).switchIfEmpty(Mono.just(user));
}
switchIfEmpty
논리적인 결정을 내리는 데는 그다지 좋지 않습니다.문서에는 다음과 같이 기술되어 있습니다.
데이터 없이 모노가 완료된 경우 대체 모노로 폴백
아무것도 얻지 못하면 다른 것으로 되돌아가는 것에 가깝기 때문에 데이터 흐름을 유지할 수 있습니다.
또한
Mono.empty().doOnNext(o -> {
throw new IllegalArgumentException("User already exists with username [" + o + "]");
}).switchIfEmpty(Mono.just("hello")).subscribe(System.out::println);
같은 문제를 겪었고 결국 아래와 같은 일을 하게 되었습니다.
참고:이는 유형 캐스트가 필요하지 않으며 두 시나리오 모두에서 작동합니다.
데이터베이스에 요소가 이미 있는 경우 오류를 발생시킵니다.
요소를 삽입하고 그렇지 않으면 Mono를 반환합니다.
public Mono<UserDTO> insertUser(User user) { return this.userRepository.findByUsername(user.getUsername()) .flatMap(foundUser-> null != foundUser ? Mono .error(new UserAlreadyExistsException(ExceptionsConstants.USER_ALREADY_EXISTS_EXCEPTION)) : Mono.just(user)) .switchIfEmpty(this.userRepository.save(user)) .map(userCreated -> copyUtils.createUserDTO(userCreated)); }
를사는대신을 사용하는 에.Mono::cast
모노의 유형을 변경하기 위해, 이것은 다음의 유형을 지정함으로써 해결될 수 있습니다.Mono.error
약간의 자바 일반 마법을 사용하는 것의 형태로.Mono.<User>error(...)
.flatMap
하지 않는 . null을 수신합니다.
이는 다음과 같습니다.
public Mono<User> insertUser(User user) {
return userRepository.findByUsername(user.username())
.flatMap(__ -> Mono.<User>error(new DuplicateResourceException("User already exists with username [" + user.username() + "]")))
.switchIfEmpty(userRepository.insertUser(user));
}
언급URL : https://stackoverflow.com/questions/58127132/how-to-perform-an-action-only-if-the-mono-is-empty-and-throw-an-error-if-not-emp
'programing' 카테고리의 다른 글
Namecheap을 사용하여 Firebase에서 사용자 지정 도메인을 확인할 수 없음 (0) | 2023.07.10 |
---|---|
특수 문자 VBA Excel 제거 (0) | 2023.07.10 |
함수 DocumentReference.set()이 잘못된 데이터로 호출되었습니다.지원되지 않는 필드 값: 사용자 지정 예산 개체 (0) | 2023.07.05 |
오류에 관계없이 ts-node를 사용하는 방법은 무엇입니까? (0) | 2023.07.05 |
where 절에 대한 Oracle/PL SQL/SQL null 비교 (0) | 2023.07.05 |