JPA

1. 사용자 정의 레포지토리 스프링 데이터 JPA 레포지토리는 인터페이스만 정의하고 구현체는 스피링이 자동 생성해준다. 스프링 데이터가 JPA가 제공하는 인터페이스를 직접 구현하면 구현해야 하는 기능이 너무 많아진다. 인터페이스의 메서드를 구현해야 하는 상황 JPA 직접 사용 스프링 JDBC Template 사용 마이 바티스 사용 데이터 베이스 커넥션 직접 사용 Querydsl 사용 메서드를 구현하기 위해서는 사용자 정의 인터페이스를 새로 만들어야한다. 1) 인터페이스 public interface MemberRepositoryCustom { List findMemberCustom(); } 2) 구현클래스 @RequiredArgsConstructor public class MemberRepositoryI..
쿼리 메서드 기능 지금부터는 더 복잡한 JPA 메서드들을 구현해보고 스프링 데이터 JPA로 바꿔보겠다. 1. 메서드 이름으로 쿼리 생성 이름과 나이를 기준으로 회원을 조회 1) 순수 JPA public List findByUsernameAndAgeGreaterThan(String username, int age){ return em.createQuery("select m from Member m where m.username = :username and m.age > :age") .setParameter("username", username) .setParameter("age", age) .getResultList(); } 순수 JPA를 사용하면 이러한 메서드를 작성해야 한다. 하지만 데이터 JPA를 사..
JPA와 스프링 데이터 JPA 스프링 데이터 JPA는 JPA를 더 효율적으로 사용하기 위한 기술이다. 데이터 JPA는 매우 유용한 기능들을 많이 제공해 주지만, JPA를 활용하는 기술이기 때문에 JPA 동작원리를 알고 있어야 한다. 데이터 JPA가 만능인것은 아니다. 동적 쿼리는 QueryDSL을 이용해야함. 1. JPA 레포지토리 다음은 JPA를 이용한 Member레포지토리이다. @Repository public class MemberJpaRepository { @PersistenceContext private EntityManager em; public Member save(Member member){ em.persist(member); return member; } public void delete..
1. OSIV JPA에서 EntityManager가 하이버네이트 에서는 Session이라고 한다. 여기서 말하는 Session이란 사용자의 데이터를 저장해주는 곳이 아니다. 따라서 OSIV(Open Session In View) 는 하이버네이트, OEIV(Open EntityManager In View) 는 JPA에서 사용된다. OSIV는 말 그대로 영속성 컨텍스트를 뷰 까지 열어두는 기능이다. Spring.jpa.open-in.view는 기본값이 True이다. 1)True 해당 값을 True로 하게 되면 트랜젝션 시작 시점에 DB와 커넥션을 맺는 영속성 컨텍스트가 생성되고 API응답이 끝날 때까지 영속성 컨텍스트와 DB커넥션을 유지한다. 따라서 지금까지 View Template이나 API Control..
V1. 엔티티 직접 노출 엔티티가 변하면 API 스펙이 변한다. 트랜잭션 안에서 지연 로딩 필요(1 + N Query) 양방향 연관관계 문제 V2. 엔티티를 조회해서 DTO로 변환(fetch join 사용X) 트랜잭션 안에서 지연 로딩 필요(1 + N Query) V3. 엔티티를 조회해서 DTO로 변환(fetch join 사용O) 페이징 시에는 N 부분을 포기해야함(대신에 batch fetch size? 옵션 주면 N -> 1 쿼리로 변경 가능) V4. JPA에서 DTO로 바로 조회, 컬렉션 N 조회 (1 + N Query) 페이징 가능 V5. JPA에서 DTO로 바로 조회, 컬렉션 1 조회 최적화 버전 (1 + 1 Query) 페이징 가능 V6. JPA에서 DTO로 바로 조회, 플랫 데이터 (1 Que..
1. 컬렉션 조회 - 플랫 데이터 최적화 V5는 괜찮게 최적화 되었지만 여전히 쿼리가 2번 나간다. 이를 1번만 나가게 하는 방법을 알아보겠다. 방법은 간단하다. 필요한 모든 데이터를 담은 DTO를 새로 만들고, 해당 데이터를 모두 가져와서 우리가 원래 반환 하려는 DTO로 변환해주면 된다. 1. DTO 생성 컬렉션 필드의 값을 채워 넣는 과정을 없애기 위해서 새로운 DTO가 필요하다. @Data public class OrderFlatDto { private Long orderId; private String name; private LocalDateTime orderDate; private OrderStatus orderStatus; private Address address; // 컬렉션 필드 대신..
컬렉션 조회 - DTO 조회 최적화 기존 V4방식에서 1 + N번 쿼리가 나가는 것을 1 + 1번 쿼리가 나가도록 하는 것이다. In절을 이용한다. public List findAllByDto() { List result = findOrders(); List orderIds = result.stream().map(o -> o.getOrderId()).collect(Collectors.toList()); List orderItems = em.createQuery( "select new jpabook.jpabook.dto.OrderItemQueryDto(oi.order.id, i.name, oi.orderPrice, oi.count) " + "from OrderItem oi " + "join oi.item ..
컬렉션 조회 - DTO로 직접 조회 1. 코드 DTO 변환 조회 메서드의 코드는 다음과 같다. @GetMapping("/api/v3/orders") public List ordersV3() { List orders = orderRepository.findAllWithItem(); List result = orders.stream() .map(o -> new OrderDto(o)).collect(Collectors.toList()); return result; } 1. DTO 생성 @Data public class OrderQueryDto { private Long orderId; private String name; private LocalDateTime orderDate; private OrderSta..
컬렉션 조회 - 페이징 V3버전은 페치 조인으로 1 + N 문제를 해결하였지만 페이징이 불가능 하다는 단점이 있었다. 페이징이 가능한 V3.1 버전을 만들어 보도록 하겠다. 1. 코드 Controller @GetMapping("/api/v3.1/orders") public List ordersV3_page( @RequestParam(value = "offset", defaultValue = "0") int offset, @RequestParam(value = "limit", defaultValue = "100") int limit) { List orders = orderRepository.findAllWithMemberDelivery(offset, limit); List result = orders.st..
컬렉션 조회 - 페치조인 최적화 V2에서는 엔티티를 직접 노출하지는 않았지만 지연로딩으로 인해 SQL문이 너무 많이 나가는 문제(1 + N 쿼리)가 발생하였다. 이를 해결하기 위해 fetch join을 사용하여 V3를 만들어 보겠다. 1. 코드 Controller @GetMapping("/api/v3/orders") public List ordersV3(){ List orders = orderRepository.findAllWithItem(); List result = orders.stream() .map(o -> new OrderDto(o)) .collect(toList()); return result; } orderRepository public List findAllWithItem() { retur..
코드 미식가
'JPA' 태그의 글 목록