1. 엔티티에는 가급적 Setter를 사용하지 말자

Setter가 모두 열려있다. 변경 포인트가 너무 많아서, 유지보수가 어렵다. 

나중에 리펙토링으로 Setter 제거

 

 

2. 모든 연관관계는 지연로딩으로 설정! ★

즉시로딩( EAGER )은 예측이 어렵고, 어떤 SQL이 실행될지 추적하기 어렵다. 특히 JPQL을 실행할 때 N+1 문제가 자주 발생한다.

즉시 로딩으로 해놓으면 연관된 데이터를 다 불러오므로 지연로딩으로 데이터를 선택적으로 가져오도록 하자

N + 1 문제: Order 데이터를 불러오기 위해 쿼리를 던졌는데 즉시로딩 으로 되어있으면 Member member; 를 불러오기위해 추가 쿼리를 날림. order가 100개면 member를 조회하기위한 100개의 쿼리가 날라감

실무에서 모든 연관관계는 지연로딩( LAZY )으로 설정해야 한다.

연관된 엔티티를 함께 DB에서 조회해야 하면, fetch join 또는 엔티티 그래프 기능을 사용한다.

@XToOne(OneToOne, ManyToOne) 관계는 기본이 즉시로딩이므로 직접 지연로딩으로 설정해야 한다.

@XToMany는 디폴트가 지연로딩( LAZY )

 

 

3. 컬렉션은 필드에서 초기화 하자.

컬렉션은 필드에서 바로 초기화 하는 것이 안전하다.

null 문제에서 안전하다.

하이버네이트는 엔티티를 영속화 할 때, 컬랙션을 감싸서 하이버네이트가 제공하는 내장 컬렉션으로 변경한다.

만약 getOrders() 처럼 임의의 메서드에서 컬력션을 잘못 생성, 수정하면 하이버네이트 내부 메커니에 문제가 발생할 수 있다. 

따라서 필드레벨에서 생성하는 것이 가장 안전하고, 코드도 간결하다.

외부에서 수정도 하지 말자. 

Member member = new Member();
System.out.println(member.getOrders().getClass());
em.persist(team);
System.out.println(member.getOrders().getClass());

//출력 결과
class java.util.ArrayList
class org.hibernate.collection.internal.PersistentBag

실제 코드에서 

private List<Order> orders = new ArrayList<>(); 부분

생성 후 수정 하지마라 있는거 그대로 써라. 하이버네이트 관리하는데 수정되면 문제가 될 수 있다.

@Entity
@Getter @Setter
public class Member {

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

    private String name;

    @Embedded
    private Address address;

    @OneToMany(mappedBy = "member") // 연관관계의 주인이 아니다 - 맵핑하는게 아니라 맵핑되는 거울이다 - 읽기 전용이다
    private List<Order> orders = new ArrayList<>();
}

 

 

4. 테이블, 컬럼명 생성 전략

스프링 부트에서 하이버네이트 기본 매핑 전략을 변경해서 실제 테이블 필드명은 다름

참조 문서 : https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/reference/htmlsingle/#howto-configure-hibernate-naming-strategy

참조 문서2 : https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#naming

 

하이버네이트 기존 구현: 엔티티의 필드명을 그대로 테이블의 컬럼명으로 사용

( SpringPhysicalNamingStrategy )

 

스프링 부트 신규 설정 (엔티티(필드) 테이블(컬럼))

  • 카멜 케이스 -> 언더스코어(memberPoint member_point)
  • .(점) ->  _(언더스코어)
  • 대문자 -> 소문자

ex) orderDate -> order_date 

 

적용 2 단계
1. 논리명 생성: 명시적으로 컬럼, 테이블명을 직접 적지 않으면 ImplicitNamingStrategy 사용

spring.jpa.hibernate.naming.implicit-strategy : 테이블이나, 컬럼명을 명시하지 않을 때 논리명 적용,

 

 

2. 물리명 적용:

spring.jpa.hibernate.naming.physical-strategy : 모든 논리명에 적용됨, 실제 테이블에 적용

(username usernm 등으로 회사 룰로 바꿀 수 있음)

 

 

스프링 부트 기본 설정

spring.jpa.hibernate.naming.implicit-strategy:

org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy

spring.jpa.hibernate.naming.physical-strategy:

org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy

'프로그래밍 > SpringBoot & JPA Use1' 카테고리의 다른 글

연관관계 (편의) 메서드  (0) 2022.06.19
casecade  (0) 2022.06.19
엔티티 클래스 개발  (0) 2022.06.19
도메인 분석 설계  (0) 2022.06.19
JPA와 DB 설정, 동작확인  (0) 2022.06.19

+ Recent posts