주문 조회 V4: JPA에서 DTO 직접 조회 OrderApiController @GetMapping("/api/v4/orders") public List ordersV4() { return orderQueryRepository.findOrderQueryDtos(); } OrderQueryRepository private final EntityManager em; /** * 컬렉션은 별도로 조회 * Query: 루트 1번, 컬렉션 N 번 * 단건 조회에서 많이 사용하는 방식 */ public List findOrderQueryDtos() { // 루트 조회(toOne 코드를 모두 한번에 조회) List result = findOrders(); //루프를 돌면서 컬렉션 추가(추가 쿼리 실행) result...
주문 조회 V1: 엔티티 직접 노출 orderItem , item 관계를 직접 초기화하면 Hibernate5Module 설정에 의해 엔티티를 JSON으로 생성한다. 양방향 연관관계면 무한 루프에 걸리지 않게 한곳에 @JsonIgnore 를 추가해야 한다. 엔티티를 직접 노출하므로 좋은 방법은 아니다. 주문 조회 V2: 엔티티를 DTO로 변환 OrderApiController @GetMapping("/api/v2/orders") public List ordersV2() { List orders = orderRepository.findAllByCriteria(new OrderSearch()); List result = orders.stream() .map(o -> new OrderDto(o)) .collec..
주문 + 배송정보 + 회원을 조회하는 API 지연 로딩 때문에 발생하는 성능 문제를 단계적으로 해결! 간단한 주문 조회 V1: 엔티티를 직접 노출 → 사용하면 안 됨! 양방향이 걸리는 곳에 @JsonIgnore을 해주어야 함 지연로딩 LAZY로 되어 있다면 실제 엔티티 대신에 프록시를 가져옴 순수한 자바 객체가 아니므로 JSON에서 오류가 발생함 Hibernate5Module 을 스프링 빈으로 등록하면 해결(스프링 부트 사용중) 간단한 주문 조회 V2: 엔티티를 DTO로 변환 엔티티를 DTO로 변환하는 일반적인 방법 쿼리가 총 1 + N + N번 실행됨 order 조회 1번(order 조회 결과 수 N) order -> member 지연 로딩 조회 N 번, order -> delivery 지연 로딩 조회..
조회용 샘플 데이터 입력 userA JPA1 BOOK JPA2 BOOK userB SPRING1 BOOK SPRING2 BOOK InitDb @Component // 클래스를 빈으로 등록 @RequiredArgsConstructor public class InitDb { private final InitService initService; @PostConstruct // 의존성 주입이 이루어진 후 빈 초기화 수행 public void init() { initService.dbInit1(); initService.dbInit2(); } @Component @Transactional @RequiredArgsConstructor static class InitService { private final Enti..
@RestController : @Controller + @ResponseBody(데이터를 json이나 xml로 보냄) @RequestBody : json 데이터를 member에 매핑해 넣어줌 @Valid : javax validation 자동으로 수행 MemberApiController 회원 등록 API @PostMapping("/api/v1/members") public CreateMemberResponse saveMemberV1(@RequestBody @Valid Member member) { //@RequestBody -> json 데이터를 member에 매핑해 넣어줌, @Valid -> javax validation 자동으로 수행 Long id = memberService.join(member)..
웹 계층 개발 회원 등록, 조회 폼 객체를 사용해서 화면 계층과 서비스 계층을 명확하게 분리한다. MemberForm @Getter @Setter public class MemberForm { @NotEmpty(message = "회원 이름은 필수입니다.") private String name; private String city; private String street; private String zipcode; } MemberController @Controller @RequiredArgsConstructor public class MemberController { private final MemberService memberService; @GetMapping("/members/new") publi..
애플리케이션 아키텍처 계층형 구조 사용 controller, web: 웹 계층 service: 비즈니스 로직, 트랜잭션 처리 repository: JPA를 직접 사용하는 계층, 엔티티 매니저 사용 domain: 엔티티가 모여 있는 계층, 모든 계층에서 사용 패키지 구조 jpabook.jpashop domain exception repository service web Repository //ex) MemberRepository @Repository // spring bean으로 자동 등록됨 @RequiredArgsConstructor // final 있는 필드만 가지고 생성자 만들어 줌 public class MemberRepository { //@PersistenceContext spring이 엔티티 ..
요구사항 분석 + 상품 주문시 배송 정보를 입력할 수 있다. 도메인 모델과 테이블 설계 회원 엔티티 분석 회원 테이블 분석 엔티티 클래스 개발 실무에서는 가급적 Getter는 열어두고, Setter는 꼭 필요한 경우에만 사용하는 것을 추천 엔티티를 변경할 때는 Setter 대신에 변경 지점이 명확하도록 변경을 위한 비즈니스 메서드를 제공해야 함 테이블은 타입이 없으므로 구분이 어려워 관례상 "테이블명 + id" 를 많이 사용한다. 실무에서는 @ManyToMany 를 사용 x 중간 테이블( CATEGORY_ITEM )에 컬럼을 추가할 수 없고, 세밀하게 쿼리를 실행하기 어렵기 때문에 실무에서 사용하기에는 한계 존재 일대다, 다대일 매핑으로 풀어내서 사용 값 타입은 변경 불가능하게 설계해야 한다. JPA 스..