티스토리 뷰
@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "username", "age"})
public class Member {
@Id
@GeneratedValue
@Column(name = "member_id")
private long id;
private int age;
private String username;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
private Team team;
public void changeTeam(Team team) {
this.team = team;
System.out.println("team :" + team);
Member member = this;
System.out.println("member :" + member);
List<Member> members = team.getMembers();
System.out.println("members :" + members);
members.add(member);
}
}
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "name"})
@Getter
public class Team {
@Id
@GeneratedValue
@Column(name = "team_id")
private long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
public Team(String name, List<Member> members) {
this.name = name;
this.members = members;
}
public Team(String name) {
this.name = name;
}
}
@RequestMapping("/test")
@Transactional
public void test(){
Team team = new Team("team2", new ArrayList<>());
Team team2 = new Team("team3");
Team team3 = Team.builder().name("develop").build();
em.persist(team);
System.out.println(team.getMembers());
System.out.println(team2.getMembers());
System.out.println(team3.getMembers()); // NullPontException
}
마지막 team3의 경우에만 team3.getMembers를 하니 NullPointException이 발생하였다.
원인을 확인해보니, Builder 패턴으로 작성한 경우에는 내부에 선언된 List members = new ArrayList();로 데이터를 초기화 안해준다고 한다.
Build 패턴으로 생성된 `team` 객체의 `members` 필드가 `null`인 이유는 `members` 필드에 대한 초기화가 `@Builder` 어노테이션에 의해 자동으로 처리되지 않았기 때문입니다.
`@Builder` 어노테이션은 빌더 패턴을 사용하여 객체를 생성할 때 필드 초기화를 자동으로 처리해주는 기능을 제공합니다. 그러나 `members` 필드는 `ArrayList`로 선언되었지만, `@Builder` 어노테이션에서 해당 필드를 초기화하는 설정이 포함되어 있지 않아서 `null`로 초기화되었습니다.
반면에 `team2`와 `team3` 객체는 직접 생성자를 통해 초기화되었기 때문에 `members` 필드에는 명시적으로 빈 리스트(`new ArrayList<>()`)가 할당되어 있습니다. `ArrayList` 생성자 호출에 의해 새로운 빈 리스트가 생성되고, 이를 `members` 필드에 할당함으로써 `null`이 아닌 빈 리스트가 됩니다.
따라서, `team` 객체의 `members` 필드를 초기화하려면 `@Builder` 어노테이션 설정에서 `members` 필드에 대한 초기화를 추가해주어야 합니다. 예를 들면 다음과 같이 할 수 있습니다:
@Builder
public class Team {
// ...
@Builder.Default
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
// ...
}
`@Builder.Default` 어노테이션을 사용하여 `members` 필드를 기본값으로 초기화할 수 있습니다. 이렇게 설정하면 `team.getMembers()`는 빈 리스트로 초기화됩니다.
'java_basic' 카테고리의 다른 글
람다와 익명클래스는 람다가 정의된 메서드의 지역변수의 값은 바꿀 수 없다 (1) | 2023.03.11 |
---|---|
파일다운로드 (0) | 2022.11.17 |
Lambda 기초5 최종연산 reduce (0) | 2022.02.16 |
Lambda 기초4 중간연산2 (0) | 2022.02.16 |
Lambda 기초4 중간연산1 (2) | 2022.02.14 |
- Total
- Today
- Yesterday
- Intellij
- stream
- nginx
- java
- elasticsearch
- 영속성 컨텍스트
- 중간연산
- Vue
- AnnotationConfigApplicationContext
- mvn
- webpack
- 자바8
- ngnix
- 스트림
- 차이
- vscode
- docker
- NPM
- container
- 람다
- 최종연산
- lambda
- Vuex
- JPA
- springboot
- BeanFactory
- map
- install
- ApplicationContext
- MAC
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |