인프런 커뮤니티 질문&답변

작성자님의 프로필 이미지

작성한 질문수

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

주문 목록 검색, 취소

안녕하세요

작성

·

502

0

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.

1. 강의 내용과 관련된 질문을 남겨주세요.
2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.
(자주 하는 질문 링크: https://bit.ly/3fX6ygx)
3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.
(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)

질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.
=========================================
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예/아니오)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)

[질문 내용]
영한님 강의를 들으면서 내용을 일부 수정해서 공부를 하고 있습니다 . 세션 부분인데요 영한님 강의에서는 JPA 를 사용하지 않았지만 저는 JPA 를 사용해보았습니다.

 

하지만 계속

WARN 11252 --- [io-8080-exec-10] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException: Failed to convert value of type 'java.util.Optional' to required type 'project.PointWeb.Domain.Member'; Cannot convert value of type 'java.util.Optional' to required type 'project.PointWeb.Domain.Member': no matching editors or conversion strategy found]

 

이 에러가 발생해서 고민중입니다.

Optional 이 문제인 것 같은데 어떻게 변경을 해야 할 지 모르겠습니다.

 

강의 내용을 조금 변경해서 실습을 하고 있어서 질문드릴까 고민했지만, 해결할 수 있는 방법을 찾지 못해서 질문 드립니다.... 감사합니다

답변 2

0

안녕하세요, 작성자 님. 공식 서포터즈 y2gcoder 입니다.

일단 원인은 알고 계신 것처럼 Optional 관련 문제가 맞습니다. 그래서 보이는 부분만 보면 SessionAttribute에 넣을 때 optional 객체에서 값을 꺼내준 다음 넣으셔야 할 것 같습니다.

그리고 제 개인적으로는 2가지 중 마음에 드시는 쪽으로 수정하시는 것을 추천드립니다.

  1. MemberRepository에서 JpaRepository를 상속받고 있습니다. JpaRepository를 상속받으면 Spring Data JPA에서 자동적으로 해주는 일이 많은 대신 그만큼 제약이 있습니다. 특히 findBy~ 문들은 거의 규칙대로 작성해주셔야 합니다. findById로 해주셔야 하고, 무엇보다 findById()가 이미 있습니다.
    이를 임의로 수정하기는 것은 손해가 많습니다. JpaRepository를 상속받아서 한다면 저는 MemberRepository를 MemberJpaRepository로 이름을 변경한 후, 이에 의존하는 MemberRepository를 둘 것 같습니다.
    MemberRepository - MemberJpaRepository(기존의 MemberRepository)
    그리고나서 MemberRepository에 원하시는대로 Member findById(Long id)를 만든 뒤, 해당 메서드에서는 MemberJpaRepository 가 자동으로 만들어주는 Optional<Member> findById(Long id)로 Optional 객체를 받아온 다음, Member가 있는지 확인하고 꺼내서 리턴해주는 식으로 해줄 수 있을 것 같습니다.

    @Repository
    public class MemberRepository {
        private final MemberJpaRepository memberJpaRepository;
    
        public MemberRepository(MemberJpaRepository memberJpaRepository) {
            this.memberJpaRepository = memberJpaRepository;
        }
        
        //...생략
        
        public Member findById(Long id) {
            return memberJpaRepository.findById(id).orElseThrow(Member엔티티찾지못했을때예외);
        }
    }
    //기존 MemberRepository
    public interface MemberJpaRepository extends JpaRepository<Member, Long> {
        Optional<Member> findByMemberId(String memberId);
    
        //기존 findById 삭제
    }

     

  2. 다른 방식으로는 해당 링크처럼 MemberRepository에서 JpaRepository가 아닌 Repository로 상속받는 것입니다. 이렇게 하면 쿼리 메서드 형식만 지켜주면 자기가 원하는대로 메서드를 만드실 수 있습니다. Member findById(Long id) 로 만드실 수 있습니다. 대신 이 때는 save나 기존에 자동으로 만들어주던 것들도 임의로 만들어서 사용하셔야 합니다.

    public interface MemberRepository extends Repository<Member, Long> {
        Member findById(Long id);
        Member save(Member member);
        //...
    }

 

 


감사합니다.

작성자님의 프로필 이미지
작성자
질문자

답변 진짜 감사합니다. 생각보다 엄청 친절하게 답변주셔서 감사합니다!!! 다시 해보겠습니다!!

감사합니다~
파이팅입니다!

작성자님의 프로필 이미지
작성자
질문자

안녕하세요 계속 시도해보다가 궁금한점이 생겨서 질문드립니다,

"SessionAttribute에 넣을 때 optional 객체에서 값을 꺼내준 다음 넣으셔야 할 것 같습니다."

 

라고 하셨는데 어떻게 값을 꺼낼수 있을까요?

Optional 객체에서 값을 꺼내는 방법은

optional.orElseThrow() 나 optional.orElse(), optional.orElseGet(), optional.get() 등 다양한 방법을 지원합니다. Optional 객체에 대해서 잘 모르신다면 Java Optional 객체에 대해서 먼저 공부해보시는 것을 권해드립니다 :)

작성자님의 프로필 이미지
작성자
질문자

계속 질문 드려서 죄송합니다.

Optional 자체의 값을 꺼내는 것은 알겠지만 제가 작성한 컨트롤러 코드 매개변수 내에서 optional 값을 꺼내보려고 계속 시도했는데 방법을 잘 모르겠습니다.

 

번거롭게 해드려서 죄송합니다..

아닙니다~ 제가 작성자 님의 질문을 오해했습니다. 죄송합니다.

위에 올려주신 코드를 보면 SessionAttribute에 LOGIN_MEMBER를 키로 가진 value값을 Member 타입으로 꺼내오는 것으로 보입니다. 여기서 예외가 나서 올려주신 것으로 이해했고,
예외 내용이 Optional 타입을 Member 타입으로 변환할 수 없다는 것이었습니다.

그래서 저는 Session에 해당 객체를 저장할 때, Optional 객체를 그대로 넣으신 것으로 이해했고 Session에 객체를 넣을 때 Optional 객체에서 저장할 객체를 꺼내 Session 객체에 넣으셔야 한다고 답변을 드렸습니다.

혹시 Session에 해당 객체를 저장하실 때 Optional 객체를 그대로 넣으신 게 아니시란 말씀이실까요?

세션에 값을 LOGIN_MEMBER를 키로 하여 값을 넣어주는 부분의 코드를 보여주시겠습니까?

작성자님의 프로필 이미지
작성자
질문자

답변 감사합니다. 제가 궁금했던 부분은 영한님은 jpa 사용 시 optional 을 주로 이용해서 member 객체를 반환하셨는데, 세션 기능 부분은 jpa 를 사용하지 않고 실습을 하셨습니다. 그래서 세션 부분에서 만약 jpa 를 사용하면 어떨지 공부하던 참에 optional 부분에서 막혔었습니다.

 

image

image

image

image

이런 식으로 코드를 짰습니다. JpaRepository 에서 optional 로 Member 를 받아서 문제가 생긴 것 같은데 Controller 에서 매개변수에 optional 로 받으려고 했는데 실패하였습니다. Contoller 부분에서 어떻게 해야 오류 없이 작동할지 고민입니다.

 

친절한 답변 정말 감사합니다!!

엇 마지막 답변에서 말씀하시고자 하는 바를 이해하지 못했는데, 위에 단 답변에서 코드가 필요하다고 한 것은 Session에 Login한 Member를 저장하는 로직의 코드입니다!

위에 올려주신 코드는 원래 질문에서 올려주신 코드들과 차이가 없는 것으로 보입니다 :)

작성자님의 프로필 이미지
작성자
질문자

와...해결했습니다 진짜 감사합니다 1주일 넘게 고민했었는데 덕분에 해결했습니다.. 감사합니다!!

헉... 일주일이나 되셨군요!
고생많으셨습니다 ㅎㅎ
열심히 문제 해결하려고 하시는 모습이 정말 멋있습니다.
파이팅입니다!

0

It seems return type of the method findByid(Long id) should be Optional(Member).

작성자님의 프로필 이미지
작성자
질문자

Thank you~