본문 바로가기

JPA

JPA 학습 (김영한)

1) NoArgsConstructor, AllArgsConstructor 관련 에러

requestBody에 json으로 매칭될 때 

NoArgsConstructor 없이 AllArgsConstructor만을 객체에 선언해 줄 경우 컴파일러는 우선적으로 전체 필드를 가지는 생성자를 우선적으로 생성하기 때문에, 기본생성자를 필요로 한 경우에도 전체 필드를 가지는 생성되가 호출되면서 에러가 발생한다.

No, All 생성자를 같이 사용해주는 것이 이러한 에러문제에서 자유로워질 수 있다.

 

 


2) Controller와 쿼리의 분리

 

update 후에 return 값을 member로 받아서 getId를 호출해되 되는데 그렇게 하지 않는이유

 

update후 entity의 값이 변경하고 그냥 끝내라.. 거기서 member를 리턴값으로 받지마라(id값만 가져오는 것은 괜찮)

Controller와 쿼리를 분리하는 습관을 들이면 유지보수성이 증가한다.

 

update 후에 return 값을 member로 받을 경우 영속상태가 끝난 상태에서 가져오기 때문에

끝내지 않고 id를 가지고 다시 조회하게 되면서 쿼리를 분리하지 못한 상태가 된다.

필요하다면 id 정도만 반환하는게 좋다. 

 

 


3) @JsonIgnore

 

public class Member {

    @JsonIgnore
    @OneToMany(mappedBy = "member")
    private List<Order> orders = new ArrayList<>();
}
양방향이 걸리는 곳은 모두 한 쪽에 @JsonIgnore를 붙여야 피할 수 있다.
  • Order - Member
  • Delivery - Order
  • OrderItem - Order

 

 


4) jpa를 통해 api를 만들 때 주의점

만약 위와 같이 [] 배열로 시작하는 데이터에 count 변수를 추가하려고 하면 추가할 수가 없다.

스팩이 굳어버려서 스팩 확장을 할 수가 없다.

위처럼 객체로 시작하는 것을 명심하자.

 

방식1

 

 

방식2

객체로 감싸서 반환하게 되면 위처럼 사용가능하다... 

 

 


5) fetch join을 이용하는 이유

 

해당 부분 호출시 

 

조회되는 order 수가 2개라고 가정하면

 

order 1번 , member1번, address 1번 , member1번, address 1번  -> 총 5번

 

(egal 사용시)

처음에 order를 가져오고 까봤더니 member, delivery가 있네?? 라면서 다 가져오기 때문에 절대로 사용해서는 안된다.

 

fetch join을 사용하게 되면

 

 

한방의 쿼리로 다 가져오게 된다... 

 

 


6) jpql 이용시 생성자를 이용하는 경우의 장단점

 

o를 한번에 넘긴다고 엔티티가 넘어가지 않는다...

엔티티가 아니라 식별자이기때문에 o.id, o.name 이렇게 일일이 넘겨야하고

받는 dto의 생성자에서 해당 파라미터를 다 받도록 처리해야한다.

 

우열을 가릴 수없다..

재사용성을 택하느냐 성능최적화를 좀 더 챙기느냐의 차이.... 

하지만 dto와 의존성이 생기기때문에 사용 안하는 것을 권장한다.... 

 

select 절보다 join 절에 의해서 성능이 좀 먹는다..

고객이 실시간으로 계속 누르는 거 아닌이상(트래픽이 높은 게 아닌 이상) 

성능 최적화를 너무 생각할 필요가 없다... 

 

 

 


7) jpql 이용시 distinct를 사용하는 이유

 

쿼리가 너무 너무 많이 나간다... 루프 돌때마다 나간다.. lazy로딩으로 인해... 

 

 

order (1) > orderItem (다) 인 상태로 가져오면 order의 데이터가 2개라도 orderitem 4개의 데이트를 조인해서 가져오게 된다. 

 

결과도 똑같이 나온다... 

 

db의 distinct + 한가지를 더해준다...

 

db 쿼리에서는 distinct가 반영이 되지않는다... 해당 중복컬럼이 다 일치해야하는데 그렇지가 않아서..

jpa에서 중복 로우를 제외하고 하나만 반환해 준다..!

 

order의 중복을 제외하고 orderItems 2개를 따로 담아져있음...

jpa가 distinct를 이용해서 해당 처리를 해줌.!

 


8) distinct 단점을 보완한 @Batchsize

 

 

 

member, delivery는 toOne으로 끝나기 때문에 fetch join을 써도 N+1의 문제가 생기지 않는다.

하지만 OrderItem은 toMany로 끝나기 때문에 fetch join을 사용하면 

중복 order를 가져오게 된다... 위처럼 distinct를 사용하면 될 수 있겠지만 결과값으로 2개만 가져오지만

그러한 부분은 jpa가 최적화를 진행해 준 것이고 db로 나가는 쿼리는 order 중복이 있는 orderItem(4개) 기준으로

4개를 가져오게된다.

그래서 페이징 처리를 하면 4개 기준으로 페이징 처리가 되므로 사용할 수가 없다....

 

하지만 페이징 처리를 할 수 있는 방법이 있다... 

 

@Batchsize를 사용하면 해당 

orderDto에서 orderItem을 가져오는 부분이 일어나도

fetch join이 걸려있지 안으므로 lazy 방식에 의해 한개씩 단건으로 여러개의 쿼리를 가져올 텐데

batchsize로 인해서 sql in절을 통해 ( 11, 44) 한번에 묶어서 가져오므로 한번의 쿼리로 가능해진다. 

 

해당 item의 이름을 가져오는 부분도 in ( ??, ??, ??) 과 같이 가져오게 된다.

order 조회 한번

orderItem 조회 한번

item조회 한번 

 

3번의 조회로 가능해 진다.

 

batch-size를 100으로 설정함녀

데이터가 1000 개면 100개씩 10번으로 나눠서 in절에 담기며

1000으로 설정하면 한번에 가져온다.. 하지만 sql -> application으로 부하가 늘어나므로 

편하게 그냥 500으로 설정해두면 괜찮다. 

 

toMany로 가는 부분에 어노테이션으로 설정하거나

 

 

toOne으로 가는 부분은 class 위에 편하게 설정해둬도 가능하지만

 

 

 

application.에 설정해두는 것이 유지보수에 좋다.

 

 

<참고>

 

https://www.inflearn.com/course/ORM-JPA-Basic/dashboard

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런

www.inflearn.com

 

'JPA' 카테고리의 다른 글

Open Session In View - JPA  (0) 2023.02.16
jpa orderby - querydsl 사용  (0) 2022.10.18
jpa 페이징 (블로그 추천)  (0) 2022.10.17
jpa - @Transaction - detach관련  (0) 2022.10.04