inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]

31강 UserServiceV2 오류

65

woddnjs

작성한 질문수 2

0

31강에서 BookService 클래스에 강의와 똑같이 코드를 작성하였는데 실행하면 UserServiceV2 오류가 발생합니다.

UserRepository의 Optional<User> 형식을 받지 못해서 생기는 오류인 것 같은데, 어떻게 수정해야 하나요?

error: incompatible types: Optional<User> cannot be converted to User

User user = userRepository.findByName(name);

^

@Transactional
public void deleteUser(String name) {
    //SELECT * FROM user WHERE name = ?
    User user = userRepository.findByName(name);
    if (user == null) {
        throw new IllegalArgumentException();
    }
    userRepository.delete(user);
}
@Transactional
public void loanBook(BookLoanRequest request){
    //1. 책 정보 가져오기
    Book book = bookRepository.findByName(request.getBookName()).orElseThrow(IllegalArgumentException::new);

    //2. 대출 기록 정보 확인하여 대출 중인지 확인
    //3. 대출 중이면 예외 발생
    if(userLoanHistoryRepository.existsByBookNameAndIsReturn(book.getName(), false)){
        throw new IllegalArgumentException("진작 대출되어 있는 책입니다.");
    }

    //4. 유저 정보 가져오기
    User user = userRepository.findByName(request.getUserName())
            .orElseThrow(IllegalArgumentException::new);

    //5. 유저 정보와 책 정보 기반 UserLoanHistory 저장
    userLoanHistoryRepository.save(new UserLoanHistory(user.getId(), book.getName()));
}

추가로 이렇게 수정하였을 때, 이후 코드를 작성할 때 Optional 형식이 아니어서 발생하는 다른 오류가 없는지도 궁금합니다.

package com.group.libraryapp.domain.user;

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface UserRepository extends JpaRepository<User, Long> {
    User findByName(String name);
}
@Transactional
public void loanBook(BookLoanRequest request){
    //1. 책 정보 가져오기
    Book book = bookRepository.findByName(request.getBookName()).orElseThrow(IllegalArgumentException::new);

    //2. 대출 기록 정보 확인하여 대출 중인지 확인
    //3. 대출 중이면 예외 발생
    if(userLoanHistoryRepository.existsByBookNameAndIsReturn(book.getName(), false)){
        throw new IllegalArgumentException("진작 대출되어 있는 책입니다.");
    }

    //4. 유저 정보 가져오기
    User user = userRepository.findByName(request.getUserName());
    if(user == null){
        throw new IllegalArgumentException();
    }

    //5. 유저 정보와 책 정보 기반 UserLoanHistory 저장
    userLoanHistoryRepository.save(new UserLoanHistory(user.getId(), book.getName()));
}

java spring aws mysql spring-boot jpa

답변 1

0

최태현

안녕하세요! 🙂 질문 주셔서 감사합니다.

하나씩 말씀드려 보면.. 먼저

UserRepository의 Optional<User> 형식을 받지 못해서 생기는 오류인 것 같은데, 어떻게 수정해야 하나요?

는 추측해주신 내용이 맞습니다.

User user = userRepository.findByName(name);

라는 코드가 있을 때 findByName()Optional<User> 를 반환한다면, User 타입이 아닌 Optional<User> 로 받아야 합니다.

혹은 아예 findByName()이 User 를 반환하게 하고, 서비스 단에서 null check를 해줘도 괜찮고요!

추가로 이렇게 수정하였을 때, 이후 코드를 작성할 때 Optional 형식이 아니어서 발생하는 다른 오류가 없는지도 궁금합니다.

Optional은 객체 타입만 봤을 때 이 타입이 nullable (null이 들어갈 수 있는지) 한지, non-nullable 한지 알기 어렵다 보니 탄생한 객체로, Optional 로 감싸진 Optioan<T> 는 null이 들어갈 수 있다는 것을 보여줄 뿐, Optional 을 사용하지 않는다고 해서 추후 다른 오류가 생기지는 않습니다.

 

또한

실행 시 오류는 없지만 웹UI로 테스트하면 서버 내부 오류가 발생했다고 뜹니다. 어떻게 수정해야 제대로 처리되는지 모르겠습니다.

같은 경우는 웹 UI로 API를 호출 했을 때 '어떤 서버 내부 오류'가 발생한 건지 에러 로그를 보면 조금 더 자세히 말씀드릴 수 있을 것 같습니다. 🙂

 

자세한 상황과 함께 질문 남겨주셔서 감사드리고, 오류 로그는 올려주시면 한 번도 봐보겠습니다!

woddnjs님의 BE 개발 공부를 응원합니다. 🔥 감사합니다!

0

woddnjs

감사합니다!
UserServiceV2를

@Transactional
public void deleteUser(String name) {
    //SELECT * FROM user WHERE name = ?
    Optional<User> user = userRepository.findByName(name);
    if (user == null) {
        throw new IllegalArgumentException();
    }
    userRepository.delete(user);
}

이렇게 변경하였더니 delete에서 user를 사용하지 못하는 오류가 뜨는데,

그 다음 강의(34강)에 아래와 같은 코드가 나와서 그 코드대로 작성하였더니 오류 없이 실행이 가능한데, 이렇게 사용해도 되는 걸까요?

@Transactional
    public void deleteUser(String name) {
        //SELECT * FROM user WHERE name = ?
        User user = userRepository.findByName(name)
                .orElseThrow(IllegalArgumentException::new);
        userRepository.delete(user);
    }

0

최태현

네네 아래 코드와 같이 사용하셔도 괜찮습니다.

그래도 왜 아래 코드는 되고 위의 코드는 에러가 발생하는지 그 원리를 아시면 좋을 것 같은데요! 그 이유는 Optional<User>User는 다른 타입이기 때문에 그렇습니다.

예를 들어 아래 함수를 생각해보죠

public void printList(List<Integer> numbers) {
  for (int num : numbers) {
    // num 출력
  }
}

이 함수에

printList(Set.of(1, 2, 3));

이라는 코드를 사용할 수 있을까요? 없을까요?

 

정답은, 에러가 발생합니다. 왜냐하면 Set<Integer>List<Integer>다른 타입이기 때문이죠. 마찬가지로 xxxRepository.delete(?) 는 Entity인 User 같은 타입이 들어와야 하는데 Optional<User>User 와 다른 타입 이기 때문에 에러가 발생하게 됩니다.

 

또 진행하시면서 어려운 점 있으시면 편하게 질문 남겨주세요~ 감사합니다! 🙇

패키지 구분에 대해 궁금한게 있습니다

0

29

2

리액트 관련 질문이 있습니다.

0

67

2

스프링부트 버전

0

83

2

7강 강의를 들으려고 했는데 오류가 나서 서버가 안 켜지는거 같아요.

0

64

2

33강. UserLoanHistory의 관계성에 대한 질문

1

57

2

Java JDK 버전 문의의 건

0

142

2

ec2 에서 Linux버전이 달라져서 설치가 안되는것 같은데 자료 최신화좀 해주세요.

0

91

3

h2 console 접속했을 테이블 질문

1

70

1

ec2 서버에서 스프링 실행도 되고 인바운드 설정까지 했는데 index.html 안됨

0

83

2

15강. updateUser() 질문

0

57

2

깃허브 질

0

90

2

여기까지 다 끝냈다고 하셨는데

0

83

2

왜안될까요

0

72

2

MySQL 창이안ㄴ뜹니다

0

59

2

포스트맨

0

55

1

spring 개념적인 질문

0

73

2

인텔리제이 샘플코드 실행 안됨 오류

0

150

2

aws 배포할때 .env 파일에 저장한 환경변수에 관하여 여쭤볼게 있습니다

0

90

1

마이그레이션 오류입니다.

0

179

3

Whitelabel Error Page 오류가 났습니다.

0

180

2

안녕하십니까! 오류가 났습니다.. 도와주세요 ㅜㅜ

1

99

3

궁금한게 있습니다.

0

64

2

DTO 관련

0

73

2

궁금한게 있습니다!

0

73

2