Builder 어노테이션 사용시, List 추가에 대한 NullPointerException

devkimc·2023년 5월 23일
0

🚫 에러 상황

builder 패턴을 사용하여 유저 인스턴스를 생성했고, userGroups 필드(List)에 데이터를 추가하자 NullPointException 이 발생했다.

java.lang.NullPointerException: Cannot invoke "java.util.List.add(Object)" because the return value of "user.domain.User.getUserGroups()" is null


User 엔티티

@Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User {

    ...

    @OneToMany(mappedBy = "user")
    private List<UserGroup> userGroups = new ArrayList<UserGroup>();

    @OneToMany(mappedBy = "recvUser")
    private List<Invite> invites = new ArrayList<Invite>();

}

User 생성 - builder 사용

    @Override
    @Transactional
    public User join(SocialJoinRequest socialJoinRequest) {

        User user = User.builder()
                .socialUserId(socialJoinRequest.getSocialUserId())
                .email(socialJoinRequest.getEmail())
                .nickname(socialJoinRequest.getNickname())
                .loginType(socialJoinRequest.getLoginType())
                .userType(UserType.ROLE_GENERAL)
                .build()
                ;

        return userRepository.save(user);
    }

📜 에러 원인

null 인 리스트에 데이터를 추가할 수 없다는 것이다.
엔티티에서 리스트 필드를 초기화 했음에도 불구하고 null 인 상황인다..

의심가는 건 builder 메서드를 사용 시 List 의 값은 입력하지 않았다.
알아보니 builder 패턴은 엔티티에서 초기화한 값을 무시하고 초기화를 한다.

따라서 builder 패턴 사용 시, 생성된 유저의 List 필드는 아래와 같았을 것이다.

    @OneToMany(mappedBy = "user")
    private List<UserGroup> userGroups;

🔑 해결 방법

1. 기본 생성자 사용

User user = new(socialJoinRequest.getSocialUserId(),socialJoinRequest.getEmail()...);

기본 생성자 사용시, 엔티티에서 초기화한 값으로 인스턴스를 생성하므로 List 는 null 이 아니다.

2. builder 메서드 사용 시, List 필드 초기화

    @Override
    @Transactional
    public User join(SocialJoinRequest socialJoinRequest) {

        User user = User.builder()
                ...
                .userGroups(new ArrayList<UserGroup>())
                .build()
                ;

        return userRepository.save(user);
    }

builder 메서드를 사용할 때마다 list 를 초기화 시켜줘야 하는 단점이 있다.

3. Builder.Default 어노테이션 사용

    @Builder.Default
    @OneToMany(mappedBy = "user")
    private List<UserGroup> userGroups = new ArrayList<UserGroup>();

builder 패턴으로 인스턴스 생성시, 지정한 값으로 초기화 시켜주는 방법이다.

참고 사이트

https://bbeomgeun.tistory.com/174

profile
가독성과 생산성이 좋은 코드를 지향하는 개발자입니다.

0개의 댓글