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

신들린코딩님의 프로필 이미지

작성한 질문수

실전! 스프링 데이터 JPA

예제 도메인 모델과 동작확인

멤버, 팀 테스트 코드 NullPointerException 에러

23.09.26 01:16 작성

·

462

·

수정됨

0


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

[질문 내용]
선생님과 소스는 조금씩 다르지만 문제는 없다고 보는데 도대체 왜 널포인터익셉션이 발생하는지 모르겠습니다...

 

  1. 테스트 코드 작성 시 teamA,teamB 저장 및 콘솔로 출력확인, db 저장도 확인
    [test.java]

    @SpringBootTest
    @Transactional
    @Rollback(false)
    public class MemberTest {

    @PersistenceContext
    EntityManager em;

    @Test
    public void testEntity(){

    Team teamA = Team.builder()
    .name("teamA")
    .build();

    Team teamB = Team.builder()
    .name("teamB")
    .build();

    em.persist(teamA);
    em.persist(teamB);

    System.out.println("teamA = " + teamA);
    System.out.println("teamB = " + teamB);

    Member member1 = new Member("member1", 10, teamA); // 여기서 에러 발생
    =========================
    teamA,B 객체 모두 정상 출력
    =>teamA = Team(id=1, name=teamA)

     

    =>teamB = Team(id=2, name=teamB)

  2. [team.java]


    @Entity
    @AllArgsConstructor
    @NoArgsConstructor(access = AccessLevel.PROTECTED)
    @Data
    @Builder
    @ToString(of = {"id", "name"})
    public class Team {

    @Id
    @GeneratedValue
    @Column(name = "team_id")
    private Long id;
    private String name;

    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();
    }

    3.[Member.java]


    @Entity
    @Getter
    @AllArgsConstructor
    @NoArgsConstructor(access = AccessLevel.PROTECTED)
    @Builder
    @ToString(of = {"id", "username", "age"})
    public class Member {

    @Id
    @GeneratedValue
    @Column(name = "member_id")
    private Long id;

    private String username;
    private int age;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;

    public Member(String username, int age, Team team) {
    this.username = username;
    this.age = age;
    if (team != null) {
    changeTeam(team);
    }
    }

    // 멤버는 팀을 변경할 수 있음
    // 멤버에서 변경되면 팀에 있는 멤버리스트도 변경되어야 함
    public void changeTeam(Team team) {
    this.team = team;
    team.getMembers().add(this);
    }
    }



    생성자에서 team !=null 이 아닐 때 changeTeam(team)을 호출해야 하는데 에러 로그 상 changeTeam 메소드 호출 시
    "team.getMembers().add(this);" 에서 널포인터가 발생합니다...확인 부탁드립니다!

    [에러 메세지]

     

    java.lang.NullPointerException

    at study.datajpa.entity.Member.changeTeam(Member.java:40)

    at study.datajpa.entity.Member.<init>(Member.java:32)

    at study.datajpa.entity.MemberTest.testEntity(MemberTest.java:38)


     

답변 2

0

OMG님의 프로필 이미지

2023. 09. 29. 23:35

안녕하세요. 신들린코딩님, 공식 서포터즈 OMG입니다. AI 답변에 더하여 답변 드립니다.

team이 null의 방어코드를 추가하였지만, add를 호출할 때 NPE가 발생할 수 있으므로 이 부분을 확인해보시면 좋을 것 같아요.

 

강의와 다르게 builder 어노테이션을 사용하셨는데, builder를 사용할 때 컬렉션의 NPE를 주의하셔야합니다.

아래 링크를 참고해주세요.

https://velog.io/@anak_2/Builder%EB%A5%BC-%ED%81%B4%EB%9E%98%EC%8A%A4%EC%97%90-%EC%82%AC%EC%9A%A9%EC%8B%9C-NULL-%EC%98%A4%EB%A5%98NPE-%EC%A3%BC%EC%9D%98

 

 

 

감사합니다.

0

인프런 AI 인턴님의 프로필 이미지

2023. 09. 28. 01:21

안녕하세요, 인프런 AI 인턴이에요.

NullPointerException 에러가 발생하는 이유는 Member 클래스의 teamA 변수가 null인 상태에서 Member 객체를 생성하려고 하기 때문입니다. MemberTest 클래스에서 teamA 객체를 생성하기 전에 teamA 변수에 값을 할당해야 합니다.

해결 방법으로는 다음과 같이 하면 됩니다.

  1. MemberTest 클래스에서 teamA 객체를 먼저 생성하고 값을 할당하세요.
  2. MemberTest 클래스에서 teamA 객체와 함께 Member 객체를 생성할 때 teamA 변수에 teamA 객체를 전달하세요.

예를 들어, 다음과 같이 코드를 수정할 수 있습니다.

@Test
public void testEntity() {
    Team teamA = Team.builder().name("teamA").build();
    Team teamB = Team.builder().name("teamB").build();
    
    em.persist(teamA);
    em.persist(teamB);
    
    System.out.println("teamA = " + teamA);
    System.out.println("teamB = " + teamB);
    
    teamA = em.find(Team.class, teamA.getId()); // teamA 객체 다시 조회
    
    Member member1 = new Member("member1", 10, teamA);
    
    em.persist(member1);
    
    // 테스트 코드 작성
}

이렇게 수정하면 NullPointerException 에러가 발생하지 않을 것입니다. 참고로, teamA 객체를 다시 조회하는 이유는 JPA의 EntityManager에서 현재의 영속성 컨텍스트에 존재하는 객체를 조회해야만 연관 관계 설정이 올바르게 이루어지기 때문입니다.

테스트 코드를 첨부하신 부분은 MemberTest 클래스에 작성된 것이라고 가정하겠습니다. 테스트 코드 작성에 관련된 다른 문제가 있으시다면 댓글로 알려주세요. 감사합니다.