분류 전체보기
-
컬렉션 조회 최적화 3 - 페이징과 한계점 돌파JPA/JPA 활용 2023. 8. 10. 21:30
컬렉션을 페치 조인하면 일대 다 조인이기 때문에 페이징이 불가능하다. 하이버네이트 6에서부터 중복을 제거해주긴 해지만 일대다 매핑을 하면 기대했던 것보다 데이터 양이 배로 늘어날 수 있다. 일대 다에서 1을 기준으로 페이징을 해야하는데 다수 쪽을 기준으로 페이징을 하면 문제인 것이다. Order를 기준으로 페이징을 하고 싶어도 다수쪽인 OrderItem을 조인해버리면 OrderItem이 기준이 될 수 있다. 하이버네이트는 모든 데이터를 읽어온 다음 메모리에서 페이징을 하는데, 실제로 많은 데이터를 페이징한다면 메모리 오류가 날 것이다. 장애가 생길 수 있으므로 되도록 사용하지 않는 것이 좋다. 최적화 방법 1. 먼저 일대일, 다대일 관계에서는 페치 조인을 적용해도 상관이 없으므로 페치 조인을 한다. @T..
-
컬렉션 조회 최적화 2 - fetch join으로 최적화JPA/JPA 활용 2023. 8. 10. 16:35
OrderRepository에 finAllWithItem 추가 public List findAllWithItem() { return em.createQuery("select o from Order o" + " join fetch o.member m" + " join fetch o.delivery d" + " join fetch o.orderItems oi" + " join fetch oi.item i", Order.class) .getResultList(); } 컨트롤러 @GetMapping("/api/v3/orders") public List ordersV3() { List orders = orderRepository.findAllWithItem(); List collect = orders.stream..
-
컬렉션 조회 최적화 1 - 페치 조인을 안 했을 시JPA/JPA 활용 2023. 8. 10. 15:57
@OneToMany에서의 최적화를 하는 방법은 엔티티 조회 최적화보다 조금 더 까다롭다. 여기서도 이전 방식처럼 성능이 안 나오는 것부터 점진적으로 발전해나가면서 할 예정이다. 1. 엔티티를 그대로 노출 @GetMapping("/api/v1/orders") public List ordersV1() { List all = orderRepository.findAllByString(new OrderSearch()); for (Order order : all) { order.getMember().getName(); order.getDelivery().getAddress(); List orderItems = order.getOrderItems(); orderItems.stream().forEach(o -> o.g..
-
벌크 연산JPA/JPQL 2023. 8. 9. 14:52
재고가 10개 미만인 모든 상품의 가격을 10% 상승 시키자는 가정이 있다고 하자. JPA의 update는 변경 감지 기능이 가장 좋다. 1. 재고가 10개 미만인 상품을 리스트로 조회 2. 상품 엔티티의 가격을 10% 증가 3. 트랜잭션 커밋 시점에 변경감지가 동작 하지만 이런 과정을 거치며 변경된 데이터가 100건이라면 100번의 UPDATE SQL이 실행되어야 하니까 효율적이지 않다. 하나를 변경할 때에는 변경 감지가 좋지만 한 번에 여러 건을 변경할 때에는 벌크 연산이 좋다. 벌크 연산 예제 쿼리 한 번으로 여러 테이블 로우를 변경한다. int resultCount = em.createQuery("update Member m set m.age = 20") .executeUpdate(); Syste..
-
Named 쿼리JPA/JPQL 2023. 8. 9. 14:37
Named 쿼리 - 정적 쿼리 미리 정의해서 이름을 부여해두고 사용하는 JPQL 어노테이션, XML에 정의가능 애플리케이션 로딩 시점에 초기화 후 재사용 애플리케이션 로딩 시점에 쿼리를 검증 선언 방법 @Entity @NamedQuery( name = "Member.findByUsername", query = "select m from Member m where m.username = :username" ) @Getter @Setter public class Member { @Id @GeneratedValue private Long id; private String username; private int age; @ManyToOne @JoinColumn(name = "TEAM_ID") private Te..
-
엔티티를 직접 사용하기JPA/JPQL 2023. 8. 9. 14:30
JQPL에서는 기본 SQL과 다르게 엔티티를 직접 넘길 수 있다. JPQL에서 엔티티를 직접 사용하면 SQL에서 해당 엔티티의 기본 키 값을 사용한다. 엔티티 직접 사용 - 기본 키 값 [JPQL] select count(m.id) from Member m // 엔티티의 아이디를 사용 select count(m) from Member m // 엔티티를 직접 사용 [SQL] (JPQL 둘 다 같은 SQL로 실행됨) select count(m.id) as cnt from Member m 엔티티를 파라미터로 전달 String jpql = "select m from Member m where m = :member"; Member findMember = em.createQuery(jpql, Member.class..
-
페치 조인의 한계JPA/JPQL 2023. 8. 9. 14:17
1. 페치 조인의 대상에는 별칭을 줄 수가 없다. "select t from Team t join fetch t.members as m" 뒤에 'as m'처럼 별칭을 붙일 수가 없다. 페치 조인은 연관된 데이터들을 모두 가져오는 것이기 때문에 그 중에 몇 개의 데이터만 가져온다던지 하는 쿼리는 하지 않는다. 하이버네이트에서 지원하기는 하지만 가급적 사용하지 않도록 하자. 페치 조인은 연간된 데이터를 모두 가져오는 것인데, 10개중에 5개만 가져오게 된다면 잘못하면 데이터가 지워질 수도 있거나 나중에 영속성 컨텍스트에서 문제가 될 수도 있다. 꼭 필요한 경우에는 어쩌다 한 번 쓸 수는 있지만 되도록 사용하면 안된다. 2. 둘 이상의 컬렉션은 페치 조인을 할 수가 없다. 일대 다와 일대 다의 매칭이므로 일대..
-
페치 조인(fetch join)JPA/JPQL 2023. 8. 9. 13:53
페치 조인은 JPA에서 매우 중요한 개념이고 실무에서도 너무 중요하다고 한다. 페치 조인이란? SQL 조인의 종류가 아님 JPQL에서 성능 최적화를 위해 제공하는 기능 연관된 엔티티나 컬렉션을 SQL 한번에 함께 조회하는 기능 join fetch 명령어 사용 엔티티 페치 조인 - @ManyToONE에서의 페치 조인 회원을 조회하면서 연관된 팀도 함께 조회(SQL 한 번에) [JQPL에서의 페치 조인] select m from Member m join fetch m.team [실제 실행 SQL] select M.*, T.* FROM MEMBER M INNER JOIN TEAM T ON M.TEAM_ID = T.ID Team teamA = new Team(); teamA.setName("팀A"); em.pe..