→ 자세히
나중에 애플리케이션을 개발하면서 비즈니스 메서드를 하나씩 등록하면서 리펙토링으로 Setter 제거하겠습니다.
<aside> ❗ 실무에서 setter를 entity 내 만들어쓰시는지 생성자를 통해서 해결하시는지 또는 private 처리로 생성 메서드만 노출하는지 궁금합니다.
객체를 생성할 때는 3가지 방법중 하나를 사용합니다.
엔티티에 따라 이 방법중 상황에 따라서 하나를 선택하고, 파라미터에 객체 생성에 필요한 데이터를 다 넘기는 방법을 사용합니다. 그리고 정적 팩토리 메서드나, Builder 패턴을 사용할 때는 생성자를 private 처리합니다. 객체 생성이 간단할 때는 단순히 생성자를 사용하고, 만약 객체 생성이 복잡하고, 의미를 가지는 것이 좋다면 나머지 방법 중 하나를 선택합니다.
그러면 setter가 없는데, 엔티티를 어떻게 수정할까요?
이것은 setter를 만들기 보다는 의미있는 변경 메서드 이름을 사용합니다. 예를들어서 고객의 등급이 오른다면 member.levelUp() 같은 메서드가 있겠지요? 이 메서드는 내부의 필드 값을 변경하고요.
핵심은 정적 팩토리, 단순 생성자, 빌더, 어떤것을 사용하든 상관이 없습니다. 중요한 것은 이렇게 생성자에 파라미터를 넘기는 기법을 사용해서, 변경이 필요없는 필드에 추가적인 setter를 외부에 노출하는 것을 줄이는 것이 핵심입니다.(생성 이후에 변경할 필요가 없는데, setter가 외부에 노출되어 있으면 이것을 사용하는 다른 개발자들은 이 setter를 호출해야 하나? 말아야 하나 고민하니까요. 그런데 setter나 변경 가능한 메서드가 없으면, 아 이건 내가 막 변경하면 안되는구나 생각하겠지요.)
외부에 어떤 것을 공개할지 객체 생성을 목적으로 하는 것이기 때문에 외부에 한가지 방식만 제공하면 됩니다.
그리고 추가로 setter를 어느정도는 허용하셔도 됩니다.(단 관리를 잘 하여야 합니다.) 연관관계를 양방향으로 적용하시려면 필연적으로 들어가야 할 때도 있더라구요.
</aside>
즉시로딩( EAGER )은 예측이 어렵고, 어떤 SQL이 실행될지 추적하기 어렵습니다. 특히 JPQL을 실행할 때 N+1 문제가 자주 발생합니다.
→ 자세히
실무에서 모든 연관관계는 지연로딩( LAZY )으로 설정해야 합니다.
연관된 엔티티를 함께 DB에서 조회해야 하면, fetch join 또는 엔티티 그래프 기능을 사용해서 최적화하면 됩니다.
@XToOne(OneToOne, ManyToOne) 관계는 기본이 즉시로딩이므로 직접 지연로딩으로 설정해야 합니다.
→ 자세히
<aside> 🌟 [TIP]
Command + Shift + F
: 전체 파일에서 찾기
</aside>
컬렉션은 필드에서 바로 초기화 하는 것이 안전합니다.
@OneToMany (mappedBy = "member")
private List<Order> orders = new ArrayList<>();
그러면 null 문제에서 안전합니다.