강의

멘토링

로드맵

Inflearn brand logo image

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

sin9801님의 프로필 이미지
sin9801

작성한 질문수

실전! Querydsl

조회 API 컨트롤러 개발

InitMember 클래스 질문

해결된 질문

작성

·

107

0

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

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

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

[질문 내용]
여기에 질문 내용을 남겨주세요.

안녕하세요. 강사님의 강의를 들으며 코드를 작성하던 도중 해결되지 않는 의문이 생겨 질문게시판에 글을 남깁니다.

 

강의를 보며 샘플데이터 추가를 위한 코드를 작성하고 나서 QuerydslApplication을 실행하면

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'initMember': Invocation of init method failed 이라는 오류코드가 뜨면서 QuerydslApplication실행이 종료 됩니다.

 

그런데 김영한 강사님이 올려주신 자료의 코드를 넣어서 실행해 보면 QuerydslApplication 실행이 잘 됩니다. 분명 똑같이 만들었는데 왜 이런 차이가 나는걸까요? 코드도 다른점이 없어보이는데 이러한 차이가 생기는 이유가 궁금합니다.

 

아래는 제가 작성한 코드(수정 전 샘플데이터)와 김영한 강사님의 코드(수정후 샘플데이터)입니다.

 

package study.querydsl;

import jakarta.annotation.PostConstruct;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import study.querydsl.entity.Member;
import study.querydsl.entity.Team;

//샘플데이터 추가

/*수정 전 샘플데이터*/

/*@Profile("local")
@Component
@RequiredArgsConstructor
public class InitMember {
    private final InitMemberService initMemberService;
    @PostConstruct
    public void init() {
        initMemberService.init();
    }
    @Component
    static class InitMemberService {
        @PersistenceContext
        private EntityManager em;
        @Transactional
        private void init() {
            Team teamA = new Team("teamA");
            Team teamB = new Team("teamB");
            em.persist(teamA);
            em.persist(teamB);
            for (int i = 0; i < 100; i++) {
                Team selectedTeam = i % 2 == 0 ? teamA :teamB;
                em.persist(new Member("member" + i, i, selectedTeam));
            }
        }
    }
}*/

/*수정후 샘플데이터*/

@Profile("local")
@Component
@RequiredArgsConstructor
public class InitMember {
    private final InitMemberService initMemberService;
    @PostConstruct
    public void init() {
        initMemberService.init();
    }
    @Component
    static class InitMemberService {
        @PersistenceContext
        EntityManager em;
        @Transactional
        public void init() {
            Team teamA = new Team("teamA");
            Team teamB = new Team("teamB");
            em.persist(teamA);
            em.persist(teamB);
            for (int i = 0; i < 100; i++) {
                Team selectedTeam = i % 2 == 0 ? teamA : teamB;
                em.persist(new Member("member" + i, i, selectedTeam));
            }
        }
    }
}

답변 1

0

안녕하세요, 인프런 AI 인턴입니다. sin9801님.

강사님의 강의를 통해 실습 중이시군요. 해당 문제는 @Transactional과 메서드 접근 제한자에 의해 발생한 것으로 보입니다.

문제의 원인:

  1. 메서드 접근 제한자: @Transactional이 적용된 메서드는 기본적으로 public 접근 제한자를 가져야 합니다. Spring에서는 프록시 기반으로 AOP를 구현하고 있는데, 이 프록시가 메서드를 호출할 때, private으로 선언된 메서드엔 트랜잭션을 적용하지 못하게 됩니다. 따라서 yourcode에서는 private로 되어 있어서 트랜잭션 관리가 되지 않은 것입니다.

  2. 프로파일 지정: @Profile("local") 어노테이션으로 인하여, 애플리케이션이 실행될 때 프로파일이 local로 설정되지 않으면 해당 빈이 생성되지 않습니다. 설정을 확인하여 프로파일이 맞게 설정되어 있는지 확인해주세요.

해결 방법:

  • 수정 후 코드에서와 같이 @Transactional을 적용할 메서드를 public으로 변경하면 트랜잭션이 정상적으로 동작할 것입니다.

추가적으로 기존답변과 같은 맥락에서 도움이 될 수 있는 자료를 링크해드립니다:

위 링크를 통해 유사한 상황에서 어떻게 문제를 해결할 수 있는지 참고하실 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

sin9801님의 프로필 이미지
sin9801

작성한 질문수

질문하기