엔티티 설계 tip
getter 는 모두 열되, setter 는 필요에 의해서 메서드를 추가하자.
getter 는 모두 열어두어도 조회만 하는 메서드이기에 별 상관 없음
setter 는 모두 열어두게 되면 변경점을 파악하기 어려워져 운영도 어려워짐
id 는 컬럼명을 따로 지정해주자.
조인 시 햇갈리지 않음
관례상 많이 사용됨
그냥 id 로 사용하는 것과 취향 차이임 (https://stackoverflow.com/questions/1369593/primary-key-foreign-key-naming-convention)
실무에서는 @ManyToMany 를 사용하지 말고 중간 엔티티을 하나 따로 빼 @ManyToOne 관계로 두 번 매핑하자.
중간 테이블에 FK말고 다른 컬럼을 추가할 일이 생길 것이다.
세밀한 쿼리하기에도 어렵다
임베디드 값 타입을 사용하는 경우 불변 객체로 만들자.
값을 바꿀 일이 있는 것이 이상한 것
생성자에서만 값을 받자.
JPA에서 엔티티나 임베디드 값 타입은 클래스 중간 조작 방식들을 사용하여 값을 삽입해주기 때문에 기본 생성자도 꼭 필요하긴 하다. 그러나, 클라이언트 코드상에서는 사용할 일이 없으므로 기본 생성자를 protected 접근자로 설정하여 생성하자.
실무에서 JPA 코드로 바로 테이블을 생성하지 말고 출력된 DDL을 참고하여 생성하자.
연관관계를 양방향으로 설정할 때는 자주 다루는 엔티티쪽에 연관관계 편의 메서드를 작성하자.
엔티티 설계 주의점
모든 연관관계는 지연 로딩으로 설정하자.
@OneToOne, @ManyToOne 은 기본이 즉시 로딩임
연관된 엔티티를 함께 조회하고 싶을 때는 엔티티 그래프나 페치 조인을 활용하자.
컬렉션은 필드에서 초기화하자.
null 문제 방지
생성자에서 초기화하면 안댐?
성능차이 거의 없음
하이버네이트에서 엔티티를 영속화하면 컬렉션 필드를 내부 컬렉션으로 감싼다. (변경 감지나 다양한 기능 구현을 위해) 따라서, 생성자에서 초기화하게 되면 JPA가 사용하는 내부 컬렉션을 사용하지 않게 될 위험이 존재하므로 필드에서 초기화해주는 것이 알려진 best practice 이다.
하이버네이트와 달리 스프링부트와 함께 사용하는 JPA 는 테이블, 필드 기본 생성 전략이 다르다.
하이버네이트는 기본적으로 실제 엔티티명, 필드명을 테이블명과 컬럼명으로 사용한다.
스프링부트와 JPA는 기본적으로 카멜케이스를 스네이크케이스로 바꾸어 사용한다.
스프링부트에서 사용하는 기본 전략은 SpringPhysicalNamingStrategy에 있다.
논리명과 물리명을 일괄적으로 변경할 전략을 yml 파일에서 설정할 수도 있다.