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

-Setter가 모두 열려있으면 변경 포인트가 너무 많아서,

 특정 엔티티하나가 어디서 수정된 것인지 알기가어렵다. 그래서 유지보수가 어렵다.

-Setter를 안열면 어떻게 알 수 있는지는에 대해서는 추후 웹어플리케이션 개발강의에서 비즈니스 메서드를 등록하면서

 코드를 가지고 보여줄 예정!

-예제에서는 Setter를 열어둔 이유는 그때 마다 보여줄 수 있는 실습내용이 있기에 열어둠!

 나중에 리펙토링으로 Setter 제거할 예정!

 실무에서는 가급적이면 setter를 열지말자!

 

 

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

(엄청중요하다!, 수많은 장애를 극복할 수 있다!, 외워야 한다.)

a.즉시로딩을 절대로 사용하지 말자

-즉시로딩(EAGER)은 어떤 종류의 SQL이 실행될지 추측하기 어렵다.

-JPQL 실행시에는 N+1 이슈가 자주 발생할 수 있다.

-최악의 경우엔 하나 연관된 데이터(디비)를 전부 다 데리고 오기 때문에

개발시에 어려워진다.

*즉시로딩설정이 되있을시에 네이처로 전부 변경하고 튜닝을 할 수 있다.

 

그래서

-연관관계는 꼭 지연로딩(LAZY)으로 설정해야 한다.

-즉시로딩이 아니어도 원하는 데이터를 실시간으로 선택하여 가져올 수 있는 방법이 있다.

 연관된 엔티티를 함께 DB에서 조회해야 할 경우는 fetch join/엔티티 그래프 기능 사용권장

 

*즉시로딩이 있고 지연로딩이 있다.

즉시로딩

-멤버를 조회할 때 연관된 필요한 주문을 다른 조회한다.

로딩하는 시점(멤버를 조회)에 다른 연관된 주문들도 로딩하겠다는 의미

 

*지연로딩의 장점

order를 조회할 때 member를 이렇게 설정해놓을 시에

@ManyToOne(fetch = FetchType.EAGER)

@JoinColumn(name = "member_id")

private Member member;

-order를 조회할 때 member 조인을 해서 쿼리 한번에 같이 조회가능하도록 한다.

한건 조회할 때는 em.find()인 경우에만 가능하다.

 

 

3. 즉시로딩일 때에는 특히 JPQL을 실행할 때 N+1 문제가 자주 발생한다.

즉시로딩의 문제 예시

예제1

@ManyToOne(fetch = FetchType.EAGER)

@JoinColumn(name = "member_id")

private Member member;

 

설명

JPQL이 제공하는 쿼리를 가지고 주문조회를 할 경우

JPQL select o From order o;

-> SQL select * from order n + 1 ( SQL문 그대로 번역을 하게 된다.)

-그러면 sql이 갈 때에는 주문 100개 조회하여 데이터 100개를 가져오지만,

-이때 member(fetch = FetchType.EAGER)를 본다.

-그래서 데이터를 100100번을 가져오기 위해 단방 쿼리가 100개를 보내게 된다.

 이것을 n+1 문제라고 한다.

 

n+1이냐

-첫 번째 주문조회를 위해 쿼리를 날려서 가져온 쿼리결과가 100개이면

 SQL select * from order n + 1에서 n100개로 치환화시키기 때문이고,

 그만큼 멤버(member)를 가져오기 위한 쿼리를 100개 보내게 된다.

 

4.@XToOne(OneToOne, ManyToOne)..x시리즈 관계는 기본이 즉시로딩이므로

직접 지연로딩으로 설정해야 한다.

 

)

@ManyToOne
@JoinColumn(name = "member_id")
private Member memebr;

@OneToMany(mappedBy = "order")
private List<OrderItem> orderItems = new ArrayList<>();

설명

@ManyToOne의 기본패치는 FetchType fetch() default EAGER;

- 얼핏 볼때에는 이것이 맞는 것 같다.

 

@OneToMany의 기본패치는 FetchType fetch() default LAZY;

 

-@OneToManyLAZY이기 때문에 따로 설정을 해줄 필요가 없지만

 @ManyToOne 디폴트가 fetch = FetchType.EAGER이므로

 직접 따로 (fetch = FetchType.LAZY)로 설정을 해주어야 한다.

*@OneToOne도 기본패치 디폴트가 fetch = FetchType.EAGER이다.

 

-설정을 해주지 않으면 연관된 하나 데이터를 가져오기 위해 쿼리 1개를 보내는 것 같지만

 연관된 데이터 조회를 위해 쿼리를 엄청나게 많이 보내게 되므로 일일이 찾아서 LAZY로 설정을 해주어야 한다.

*쿼리 종류 및 의미를 이해해야 한다.(내가부족한 것)

 

5. 실습-@ManyToOne을 찾아서 지연로딩(LAZY)로 설정을 해주자

 

a.fetch 설정하는 사진

b.그리고 나머지 @ManyToOne을 찾아서 바꿔준다.

-jpabook.jpashop에서 ctrl + shift + f를 하면 다음과 같은 화면이 나온다.

 

c.@OneToOneLAZY 지연로딩으로 변경해준다.

 

d.static import(좀더 깔끔하게 외관상 LAZY로 보여지게 하는 방법)

-FetchType위에서 alt + enter를 타입하면 위와 같이 변경이 된다.

 

*엔티티개발을 하면서 중간중간에 내가 작성한대로 생성이 되었는지 확인을 해라

*실행툴 안에 나오는 메시지에서 생성된 테이블 생성코드 그대로 작성해도 되는가 - 안된다.

 

)

create table orders (

order_id bigint not null,

order_date timestamp,

status varchar(255),

delivery_id bigint,

member_id bigint,

primary key (order_id)

);

 

-디테일하게 수정해야 할 것들이 있다. 수정하고 정리해서 사용한다.

 

+ Recent posts