30%
61,600원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
Batch Size에서 두 번째 Order의 ID가 IN 쿼리에 들어가는 이유
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용] 처음 OrderItem을 조회할 때 두 번째 Order의 ID(11)와 함께 IN 쿼리를 통해 조회됩니다. 여기서 IN 쿼리에 두 번째 Order의 ID가 들어가는 이유에 대해 생각해보았습니다. 1. 현재 Order 엔티티를 통해 OrderItem을 조회하고 있다. 2. batch가 설정되어 있기 떄문에 1차 캐시에 들어있는 Order들을 통해 최대 batch_size개 까지 IN 쿼리를 통해 조회한다. 3. 조회 대상이 된 1차 캐시에 들어있던 Order들 중에 두 번째 Order가 포함되어있었기 때문에 IN 쿼리에 두 번째 Order의 ID가 함께 들어갔다. 4. member와 delivery를 fetch하지 않았을 때도 위와 같은 이유로 한번에 조회되었다. 이런 과정을 거쳐서 같이 조회가 되지 않았나 생각해보았습니다. 제가 생각한 이유가 맞거나 혹시 틀린 부분이 있는지 궁금합니다. 감사합니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
영속성 컨텍스트 분산환경 질문
안녕하세요 짧게 질문하나 드리겠습니다 예를 들어 강의처럼 order와 member가 연결 되었다고 가정할때 order1 - member1 order2- member2 order3- member1 과 같이 데이터가 있다고 가정하겠습니다. order1이 member를 한번 불러오면 영속성 컨텍스트에 남아있기 때문에 마지막에 order3이 member1을 다시불러오면 디비가 아닌 영속성 컨텍스트에서 member1의 정보를 불러올텐데 그 사이에 다른 서버 (scale out된 3개가 서버가 하나의 db를 공유할때)가 member1의 이름을 수정했을 경우에는 어떻게 구동이 될까요? 저는 JPA 기본강의를 수강했을때 당시에 영속성 컨텍스트는 application level이라고 이해했는데 분산환경인 경우 서버가 3개면 영속성 컨텍스트도 3개가 아닌가 싶어서 질문드립니다
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
질문있습니다
안녕하세요 강사님 API 파라미터 변조에 대한 질문인데요 현재 프로젝트 구조는 프론트앤드 Vuejs, 백앤드는 spring boot로 API 제공 역할을 하고 있습니다 현재 인증방식은 세션 인증방식을 사용중이고 최초 인증 후 세션에 사용자 정보를 담아, 이후 API 요청에 대해서 인터셉터를 적용하여 인증된 사용자만 API에 접근할 수 있도록 하고 있습니다 하지만 특정 사용자가 포스트맨 같은 툴을 사용하여 인증을 완료후 API에 요청을 날릴때 특정 파라미터를 변조하거나 할 경우는 어떻게 보안처리를 할 수 있나요? 현재 통신 프로토콜은 HTTP 사용중인데, HTTPS를 사용하면 이러한 문제를 해결할 수 있나요?
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
콘솔 쿼리 모양
7분39초에나오는 jpa쿼리처럼 줄바꿈에서 콘솔에서 보려면 어떻게 하나요? 저는 1렬로 나와서 쿼리를 보기 불편해서요. 혹시나해서 제 설정파일 남길게요 spring: datasource: url: jdbc:h2:tcp://localhost/~/jpashop username: sa password: driver-class-name: org.h2.Driver jpa: hibernate: ddl-auto: create properties: hibernate: show_sql: true format_sql: truelogging: level: org.hibernate.SQL: debug # ?????? ?? org.hibernate.type: trace
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
페치조인 쿼리시 쿼리가 두번 나갑니다.
강의에서 보면 쿼리가 한번 나가는데 저는 두번이 나갑니다 ㅠㅠ http://localhost:8080/api/v3/simple-orders 호출 2022-06-26 01:02:45.805 DEBUG 5062 --- [nio-8080-exec-6] org.hibernate.SQL : select order0_.order_id as order_id1_6_0_, member1_.member_id as member_i1_4_1_, delivery2_.delivery_id as delivery1_2_2_, order0_.delivery_id as delivery4_6_0_, order0_.member_id as member_i5_6_0_, order0_.order_date as order_da2_6_0_, order0_.status as status3_6_0_, member1_.city as city2_4_1_, member1_.street as street3_4_1_, member1_.zipcode as zipcode4_4_1_, member1_.name as name5_4_1_, delivery2_.city as city2_2_2_, delivery2_.street as street3_2_2_, delivery2_.zipcode as zipcode4_2_2_, delivery2_.status as status5_2_2_ from orders order0_ inner join member member1_ on order0_.member_id=member1_.member_id inner join delivery delivery2_ on order0_.delivery_id=delivery2_.delivery_id Hibernate: select order0_.order_id as order_id1_6_0_, member1_.member_id as member_i1_4_1_, delivery2_.delivery_id as delivery1_2_2_, order0_.delivery_id as delivery4_6_0_, order0_.member_id as member_i5_6_0_, order0_.order_date as order_da2_6_0_, order0_.status as status3_6_0_, member1_.city as city2_4_1_, member1_.street as street3_4_1_, member1_.zipcode as zipcode4_4_1_, member1_.name as name5_4_1_, delivery2_.city as city2_2_2_, delivery2_.street as street3_2_2_, delivery2_.zipcode as zipcode4_2_2_, delivery2_.status as status5_2_2_ from orders order0_ inner join member member1_ on order0_.member_id=member1_.member_id inner join delivery delivery2_ on order0_.delivery_id=delivery2_.delivery_id 전체 코드 Order 엔티티 package jpabook.jpashop.domain.entity;import lombok.Getter;import lombok.Setter;import javax.persistence.*;import java.time.LocalDateTime;import java.util.ArrayList;import java.util.List;@Entity@Table(name = "orders")@Getter @Setterpublic class Order { @Id @GeneratedValue @Column(name = "order_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id") private Member member; @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) private List<OrderItem> orderItems = new ArrayList<>(); @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "delivery_id") private Delivery delivery; private final LocalDateTime orderDate = LocalDateTime.now(); @Enumerated(EnumType.STRING) private OrderStatus status; //==연관관계 메서드==// public void setMember(Member member) { this.member = member; member.getOrders().add(this); } public void addOrderItem(OrderItem orderItem) { orderItems.add(orderItem); orderItem.setOrder(this); } public void setDelivery(Delivery delivery) { this.delivery = delivery; delivery.setOrder(this); } //==생성 메서드==// public static Order createOrder(Member member, Delivery delivery, OrderItem... orderItems) { Order order = new Order(); order.setMember(member); order.setDelivery(delivery); for (OrderItem orderItem : orderItems) { order.addOrderItem(orderItem); } order.setStatus(OrderStatus.ORDER); return order; } //==비즈니스 로직==/ /** * 주문 취소 */ public void cancel() { if (delivery.getStatus() == DeliveryStatus.COMP) { throw new IllegalStateException("이미 배송완료된 상품은 취소가 불가능합니다."); } this.setStatus(OrderStatus.CANCEL); for (OrderItem orderItem : orderItems) { orderItem.cancel(); } } //==조회 로직==// /** * 전체 주문 가격 조회 */ public int getTotalPrice() { return orderItems.stream().mapToInt(OrderItem::getTotalPrice).sum(); }} controller package jpabook.jpashop.api;import jpabook.jpashop.domain.entity.Address;import jpabook.jpashop.domain.entity.Order;import jpabook.jpashop.domain.entity.OrderStatus;import jpabook.jpashop.domain.repository.OrderRepository;import jpabook.jpashop.domain.repository.OrderSearch;import lombok.Data;import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import java.time.LocalDateTime;import java.util.List;import java.util.stream.Collectors;/** * xToOne(ManyToOne, OneToOne) * Order * Order -> Member * Order -> Delivery */@Slf4j@RestController@RequiredArgsConstructorpublic class OrderSimpleApiController { private final OrderRepository orderRepository; @GetMapping("/api/v1/simple-orders") public List<Order> ordersV1() { List<Order> all = orderRepository.findAllByString(new OrderSearch()); all.stream().forEach(o -> { o.getMember().getName(); // Lazy 강제 초기화 o.getDelivery().getAddress(); // Lazy 강제 초기화 }); return all; } @GetMapping("/api/v2/simple-orders") public List<SimpleOrderDto> ordersV2() { List<Order> orders = orderRepository.findAllByString(new OrderSearch()); return orders.stream() .map(SimpleOrderDto::new) .collect(Collectors.toList()); } @GetMapping("/api/v3/simple-orders") public List<SimpleOrderDto> ordersV3() { List<Order> orders = orderRepository.findAllWithMemberDelivery(new OrderSearch()); return orders.stream() .map(SimpleOrderDto::new) .collect(Collectors.toList()); } @Data static class SimpleOrderDto { private Long orderId; private String name; private LocalDateTime orderDate; private OrderStatus orderStatus; private Address address; public SimpleOrderDto(Order order) { orderId = order.getId(); name = order.getMember().getName(); orderDate = order.getOrderDate(); orderStatus = order.getStatus(); this.address = order.getDelivery().getAddress(); } }} repository package jpabook.jpashop.domain.repository;import org.springframework.stereotype.Repository;import org.springframework.util.StringUtils;import javax.persistence.EntityManager;import javax.persistence.TypedQuery;import javax.persistence.criteria.*;import java.util.ArrayList;import java.util.List;import jpabook.jpashop.domain.entity.Order;@Repositorypublic class OrderRepository { private final EntityManager em; public OrderRepository(EntityManager em) { this.em = em; } public void save(Order order) { em.persist(order); } public Order findOne(Long id) { return em.find(Order.class, id); } public List<Order> findAllByString(OrderSearch orderSearch) { String jpql = "select o from Order o join o.member m"; boolean isFirstCondition = true; //주문 상태 검색 if (orderSearch.getOrderStatus() != null) { if (isFirstCondition) { jpql += " where"; isFirstCondition = false; } else { jpql += " and"; } jpql += " o.status = :status"; } //회원 이름 검색 if (StringUtils.hasText(orderSearch.getMemberName())) { if (isFirstCondition) { jpql += " where"; isFirstCondition = false; } else { jpql += " and"; } jpql += " m.name like :name"; } TypedQuery<Order> query = em.createQuery(jpql, Order.class) .setMaxResults(1000); if (orderSearch.getOrderStatus() != null) { query = query.setParameter("status", orderSearch.getOrderStatus()); } if (StringUtils.hasText(orderSearch.getMemberName())) { query = query.setParameter("name", orderSearch.getMemberName()); } return query.getResultList(); } /** * JPA Criteria */ public List<Order> findAllByCriteria(OrderSearch orderSearch) { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Order> cq = cb.createQuery(Order.class); Root<Order> o = cq.from(Order.class); Join<Object, Object> m = o.join("member", JoinType.INNER); List<Predicate> criteria = new ArrayList<>(); //주문 상태 검색 if (orderSearch.getOrderStatus() != null) { Predicate status = cb.equal(o.get("status"), orderSearch.getOrderStatus()); criteria.add(status); } //회원 이름 검색 if (StringUtils.hasText(orderSearch.getMemberName())) { Predicate name = cb.like(m.<String>get("name"), orderSearch.getMemberName()); criteria.add(name); } cq.where(cb.and(criteria.toArray(new Predicate[criteria.size()]))); TypedQuery<Order> query = em.createQuery(cq).setMaxResults(1000); return query.getResultList(); } public List<Order> findAllWithMemberDelivery(OrderSearch orderSearch) { return em.createQuery("select o from Order o join fetch o.member m join fetch o.delivery d", Order.class) .getResultList(); }}
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
Dto Json 출력 오류 질문
Address 필드가 Response 시 빈 객체로 나옵니다. [ { "orderId": 4, "name": "userA", "orderDate": "2022-06-26T00:43:08.07663", "orderStatus": "ORDER", "address": {} }, { "orderId": 11, "name": "userB", "orderDate": "2022-06-26T00:43:08.155045", "orderStatus": "ORDER", "address": {} } ] log를 찍어 봤는데 아래와 같이 dto에 address는 잘 들어가있습니다. 2022-06-26 00:43:11.618 INFO 4953 --- [nio-8080-exec-2] j.jpashop.api.OrderSimpleApiController : dto address = Address(city=서울, street=1, zipcode=1111) 2022-06-26 00:43:11.618 INFO 4953 --- [nio-8080-exec-2] j.jpashop.api.OrderSimpleApiController : dto address = Address(city=진주, street=2, zipcode=2222) 뭐가 문제일까요 ㅠㅠㅠ 전체코드 package jpabook.jpashop.api;import jpabook.jpashop.domain.entity.Address;import jpabook.jpashop.domain.entity.Order;import jpabook.jpashop.domain.entity.OrderStatus;import jpabook.jpashop.domain.repository.OrderRepository;import jpabook.jpashop.domain.repository.OrderSearch;import lombok.Data;import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import java.time.LocalDateTime;import java.util.List;import java.util.stream.Collectors;/** * xToOne(ManyToOne, OneToOne) * Order * Order -> Member * Order -> Delivery */@Slf4j@RestController@RequiredArgsConstructorpublic class OrderSimpleApiController { private final OrderRepository orderRepository; @GetMapping("/api/v1/simple-orders") public List<Order> ordersV1() { List<Order> all = orderRepository.findAllByString(new OrderSearch()); all.stream().forEach(o -> { o.getMember().getName(); // Lazy 강제 초기화 o.getDelivery().getAddress(); // Lazy 강제 초기화 }); return all; } @GetMapping("/api/v2/simple-orders") public List<SimpleOrderDto> ordersV2() { List<Order> orders = orderRepository.findAllByString(new OrderSearch()); List<SimpleOrderDto> result = orders.stream() .map(SimpleOrderDto::new) .collect(Collectors.toList()); result.forEach(dto -> log.info("dto address = {}", dto.getAddress())); return result; } @Data static class SimpleOrderDto { private Long orderId; private String name; private LocalDateTime orderDate; private OrderStatus orderStatus; private Address address; public SimpleOrderDto(Order order) { orderId = order.getId(); name = order.getMember().getName(); orderDate = order.getOrderDate(); orderStatus = order.getStatus(); address = order.getDelivery().getAddress(); } }}
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
영속성 컨텍스트 관련 질문
안녕하세요! 영한님 먼저 양질의 강의를 제공해주셔서 감사의 말씀 드립니다. 갑자기 영속성 컨텍스트에 대한 개념이 헷갈려서 질문드립니다. 😭 만약에 order테이블에서 member의 id가 동일한 경우 ordersV2()를 사용하면 쿼리가 총 4번 나가는데 이때 영속성 컨텍스트에서 관리되어(1차 캐시에서 조회하기 때문으로 이해했습니다.) 기존에 있는 것을 가져온다고 말씀하셨습니다. 그런데 @Transactional 안에서 DB를 조회해야 영속성 컨텍스트에서 관리되는 것 아닌가요? 🤔 감사합니다.
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
질문드립니다
항상 친절한 강의와 답변 모두 감사드립니다! 강의듣다가 두 가지 질문이있는데요. MemberService.update Method 에서 return 값으로 Member를 넘기게 되면 영속성이 끊긴다고 하셨는데 그러면 Controller 쪽에서 Member updateMember = memberService.update(id, name); 라고 하면 이 updateMember 는 준영속 상태인가요 ? 그리고 일단 기본적으로 독립된 트랜잭션마다 각각 다른 영속성 컨텍스트가 생성되는 게 맞죠? (OSIV 는 추후 듣도록 하겠습니다!)
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
aggregate 단위당 레파지토리 하나
안녕하세요 영한님 영한님 jpa강의를 쭉 들었었지만 aggregate 관련된 내용을 듣지 못한 것 같아 질문 남겨봅니다. aggregate 단위당 레파지토리 하나 라는 내용을 간혹 보게 되는데요 어떤 entity 가 여러 연관관계를 가졌다면 부모 entity의 repository만 작성해야 한다는 그런 뜻인지 궁금합니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
통계성 데이터 조회
안녕하세요. 강사님 실무에서 통계성 데이터는 어떻게 처리하는지 궁금합니다. 통계성이면.. 객체가 연관관계가 없을 수도 있을 것이고, 대량의 데이터를 조회하기도 할 것 같은데 best practice나 권장 구현 방안이 있다면 설명 부탁드립니다.
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
Entity를 DTO로 변환시키기
김영한님 JPA 강의를 듣다가 1장 마지막 부분 쯤에 Entity를 그대로 사용하지 말고 데이터를 전송할 때에는 DTO를 이용하라고 하셨는데, 테이블 끼리 연관관계가 많은 것들은 어떻게 변환시키나요? 가장 궁금한게 A에 List<B>,List<C>,List<D> 객체를 가지고 있는데 A의 DTO를 만든다고 한다면 B,C,D를 각자 또 BDTO,CDTO,DDTO 로 옮기고 나서 ADTO에 담는건가요?? MapStruct를 사용하려고 하는데, 혹시 Entity를 DTO로 변환하는 좋은 방법이 있는지 궁금합니다!
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
autocommit과 connection 획득 지연에 대해
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용] 안녕하세요. 먼저 좋은 강의 제작해주셔서 많은 도움이 되었고, 감사드립니다! osiv 를 설명해주신 강의에서, osiv가 켜져있으면 커넥션을 오래 물고 있어 트래픽이 많으면 장애가 발생할 수 있다고 하셨는데요. 같은 맥락으로 커넥션을 릴리즈하는 시점이 아닌 획득 하는 시점에서도 1. datasource에서 커넥션 autocommit을 false로 설정하고, (디폴트는 true) 2. 하이버네이트에게 트랜잭션 시작(그리고 종료) 시 set autocommit를 수행하지 않도록 해서(hibernate.connection.provider_disables_autocommit 옵션으로 하이버네이트에게 알려줌) 커넥션 획득을 지연시키고 불필요한 SET 문 실행을 없애, 결과적으로 커넥션 점유 시간을 줄이면서 리소스 사용과 쓰루풋 최적화가 가능하다고 합니다. 참고한 자료 - https://vladmihalcea.com/why-you-should-always-use-hibernate-connection-provider_disables_autocommit-for-resource-local-jpa-transactions/ - https://github.com/spring-projects/spring-boot/issues/9261 - https://pkgonan.github.io/2019/01/hibrnate-autocommit-tuning - https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/appendices/Configurations.html 그래서 위 자료들에 따르면 일반적인 스프링 부트 2 + 하이버네이트 조합을 쓰는 경우에는 datasource의 autocommit을 항상 false로 하는 것이 좋을 것 같은데(이 경우 hibernate.connection.provider_disables_autocommit는 자동으로 enable 설정됨), 혹시 이 설정에 대한 경험이 있으신지, 있으시다면 조심해야할 사이드이팩트는 없으셨는지 궁금해서 질문남겨봅니다. (늦더라도 영한님께서 직접 답변해주시면 좋을 것 같습니다^^) 감사합니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
컨트롤러 파라미터와 DTO에 대한 질문입니다.
[질문 내용]안녕하세요. 컨트롤러 파라미터에 대해서 질문이 있습니다. 보통 컨트롤러에서 @RequestBody로 DTO를 받는데요. 개인 프로젝트를 진행하면서 ,DTO 클래스를 계속 생성하게 되면 DTO파일도 많아지는 경향이 있다고 느꼈습니다. 전달받아야 할 파라미터가 1개인 경우, DTO클래스를 생성하는 것 대신, @RequestParam 혹은 Map을 활용하는 방법이 있는데요. @RequestParam을 사용하면 옵션을 줄 수 있다는 점, 올바르지 않은게 오면 400 코드를 준다는 점 정도가 다른 점이라고 생각합니다. 둘이 큰 차이가 없다고 생각하는데, Map을 사용하는 것에 대해 부정적인 의견도 많이 있는 것 같습니다. 한 개의 파라미터를 받기 위해 어느 방법을 사용하는 것이 효율적일까요? 상황마다 다른지, 보통 어떤식으로 처리하는지 궁금합니다. 감사합니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
DTO, VO, DAO, Repository에 관련한 질문드립니다.
안녕하세요 강의 정말 유익하게 잘 듣고 있습니다. 실무로 스프링을 접하며 강의를 같이 들으며 진행하고 있는데 들으면서 너무 헷갈리는 부분이 있어 문의드립니다. 1. DTO 와 VO의 차이 그리고 실무에서 어떤경우에 사용하는지 차이 DTO = 전송되는 데이터를 담는 객체 VO = getter/setter 로만 구성된 불변하는 데이터를 담는 객체 라고 표현이 되는데, 너무 와닿지가 않아서 정확한 차이점을 질문드리고 싶습니다. 추가로, 찾아본 예제들에서는 DTO와 VO를 혼합하여 사용하거나 아예 한쪽만 사용하는경우가 혼재되어 많이 헷갈립니다 실무에서는 어떤경우에 어떤 구조체를 사용하는건지 문의드립니다. 2. DAO와 Repository 의 차이점을 문의드립니다. 제가 알기론, 둘다 DB와 소통을 하는 로직을 구현하는건 같지만 DAO는 Data Persistence 를 구체화 한 것이고, 테이블과 더 Low level에서 연관성을 가지고 있고, Repository는 DAO보다 더 High level로 repository안에 여러개의 dao를 사용하여 구현하기도 하는것으로 알고 있습니다. 다만, 예제들을 찾아보면 누구는 DAO로만 구성하여 사용하고, 누구는 Repository만 구현하여 사용하여 실무에서 어떤경우에 DAO와 Repository를 사용하는지가 너무 헷갈립니다. DAO와 Repository가 실무에서 어느때에 사용되는건지 문의도 같이 드리고 싶습니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
DTO와 엔티티의 변환 작업은 어느 계층에서 하는게 좋은지에 대해 질문드립니다.
DTO 객체에서 엔티티로 또는 엔티티에서 DTO로 변환하는 작업은 컨트롤러에서 해야할까요? 아니면 서비스 단에서 해야할까요? 어느 계층에서 하는게 좋나요?
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
insert sql batch
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]안녕하세요 영한님! 강의 정말 잘 보고 있습니다. 궁금한 점은 조회할 때는 join fetch나 default_batch_fetch_size를 통해 성능 최적화를 하는데, 샘플 데이터를 넣을 때의 쿼리를 보니까 많은 쿼리가 나가는 것을 확인 했습니다. orderItem들이 생성 될 때 여러 번의 쿼리가 아니라 한 번의 쿼리로 실행되게 하는 방법이 있을까요?? insert batch 등을 검색해봤는데 잘 적용이 되지 않아 질문 남깁니다! insert into member (city, street, zipcode, name, member_id) values ('서울', '1', '1111', 'userA', 1); insert into item (name, price, stock_quantity, author, isbn, dtype, item_id) values ('JPA1 BOOK', 10000, 100, NULL, NULL, 'B', 2); insert into item (name, price, stock_quantity, author, isbn, dtype, item_id) values ('JPA2 BOOK', 20000, 100, NULL, NULL, 'B', 3); insert into delivery (city, street, zipcode, delivery_status, delivery_id) values ('서울', '1', '1111', NULL, 5); insert into orders (delivery_id, member_id, order_date, status, order_id) values (5, 1, '2022-06-08T16:23:38.605+0900', 'ORDER', 4); insert into order_item (count, item_id, order_id, order_price, order_item_id) values (1, 2, 4, 10000, 6); insert into order_item (count, item_id, order_id, order_price, order_item_id) values (2, 3, 4, 20000, 7); update item set name='JPA1 BOOK', price=10000, stock_quantity=99, author=NULL, isbn=NULL where item_id=2; update item set name='JPA2 BOOK', price=20000, stock_quantity=98, author=NULL, isbn=NULL where item_id=3;
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
@JsonIgnore 는 엔티티에서 안붙여도 되는걸까요??
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용] 강의 잘 보고 있습니다 감사합니다! 엔티티는 json으로 반환하지 않는 걸로 알고 있고 그렇게하면 안된다는 걸 이해했습니다. 그렇다면, 엔티티를 json으로 반환하지 않는 방식으로 설계를 한다면 @JsonIgnore 는 양방향 관계에서도 안붙여도 될까요??
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
distinct 질문 드립니다!
일대다 컬렉션 페치 조인 조회의 경우 팀A인 멤버가 1, 2, 3이면 DB는 멤버를 기준으로 조인을 해서 팀A인 row가 3개가 생기고 하이버네이트는 이를 받아와서 리스트로 반환(getResultList)해줄 때 리스트에 팀 A 엔티티를 3개 담아줍니다. 여기서 각각의 엔티티는 PK 값이 같기 때문에 서로 같은 엔티티를 참조합니다. (이렇게 이해를 했습니다!) 그러면 쿼리 횟수에 영향을 주는 건 페치 조인이고, distinct는 리스트에 중복 엔티티만 제거하는 역할만 하는 것 같은데 (select 다음 distinct가 추가되는 것 외에는 차이가 없음) 속도적인 면에서는 별 차이가 없는 것이 맞을까요??
- 해결됨실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
"status": 500 오류 관련 질문입니다.
안녕하세요 현재 간단한 주문조회 V4 : JPA에서 DTO로 바로조회 부분을 수강 중에 생긴 오류입니다. 아래 그림과 같이 오류가 뜨는데, 서버가 실행 되지 않아 생긴 오류는 아닌 것 같습니다. package jpabook.jpashop.api;import jpabook.jpashop.domain.Address;import jpabook.jpashop.domain.Order;import jpabook.jpashop.domain.OrderStatus;import jpabook.jpashop.repository.OrderRepository;import jpabook.jpashop.repository.OrderSearch;import jpabook.jpashop.repository.OrderSimpleQueryDto;import lombok.Data;import lombok.RequiredArgsConstructor;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import java.time.LocalDateTime;import java.util.List;import java.util.stream.Collectors;import static java.util.stream.Collectors.toList;/** * xToOne * Order * Order -> Member * Order -> Delivery */@RestController@RequiredArgsConstructorpublic class OrderSimpleApiController { private final OrderRepository orderRepository; @GetMapping("/api/v1/simple-orders") public List<Order> ordersV1() { List<Order> all = orderRepository.findAllByString(new OrderSearch()); for (Order order : all) { order.getMember().getName(); //Lazy 강제 초기화 order.getDelivery().getAddress(); //Lazy 강제 초기화 } return all; } @GetMapping("/api/v2/simple-orders") public List<SimpleOrderDto> ordersV2() { //ORDER 2개 //N + 1 -> 1 + 회원 N(2) + 배송 N List<Order> orders = orderRepository.findAllByString(new OrderSearch()); List<SimpleOrderDto> result = orders.stream() .map(o -> new SimpleOrderDto(o)) .collect(toList()); return result; } @GetMapping("/api/v3/simple-orders") public List<SimpleOrderDto> ordersV3() { List<Order> orders = orderRepository.findAllWithMemberDelivery(); List<SimpleOrderDto> result = orders.stream() .map(o -> new SimpleOrderDto(o)) .collect(Collectors.toList()); return result; } @GetMapping("/api/v4/simple-orders") public List<OrderSimpleQueryDto> ordersV4() { return orderRepository.findOrderDtos(); } @Data static class SimpleOrderDto { private Long orderId; private String name; private LocalDateTime orderDate; private OrderStatus orderStatus; private Address address; public SimpleOrderDto(Order order) { orderId = order.getId(); name = order.getMember().getName(); orderDate = order.getOrderDate(); orderStatus = order.getStatus(); address = order.getDelivery().getAddress(); } }} package jpabook.jpashop.repository;import jpabook.jpashop.domain.Order;import lombok.RequiredArgsConstructor;import org.springframework.stereotype.Repository;import org.springframework.util.StringUtils;import javax.persistence.EntityManager;import javax.persistence.TypedQuery;import javax.persistence.criteria.*;import java.util.ArrayList;import java.util.List;@Repository@RequiredArgsConstructorpublic class OrderRepository { private final EntityManager em; public void save(Order order) { em.persist(order); } public Order findOne(Long id) { return em.find(Order.class, id); } public List<Order> findAllByString(OrderSearch orderSearch) { //language=JPAQL String jpql = "select o From Order o join o.member m"; boolean isFirstCondition = true;//주문 상태 검색 if (orderSearch.getOrderStatus() != null) { if (isFirstCondition) { jpql += " where"; isFirstCondition = false; } else { jpql += " and"; } jpql += " o.status = :status"; }//회원 이름 검색 if (StringUtils.hasText(orderSearch.getMemberName())) { if (isFirstCondition) { jpql += " where"; isFirstCondition = false; } else { jpql += " and"; } jpql += " m.name like :name"; } TypedQuery<Order> query = em.createQuery(jpql, Order.class) .setMaxResults(1000); //최대 1000건 if (orderSearch.getOrderStatus() != null) { query = query.setParameter("status", orderSearch.getOrderStatus()); } if (StringUtils.hasText(orderSearch.getMemberName())) { query = query.setParameter("name", orderSearch.getMemberName()); } return query.getResultList(); } /** * JPA Criteria */ public List<Order> findAllByCriteria(OrderSearch orderSearch) { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Order> cq = cb.createQuery(Order.class); Root<Order> o = cq.from(Order.class); Join<Object, Object> m = o.join("member", JoinType.INNER); List<Predicate> criteria = new ArrayList<>(); //주문 상태 검색 if (orderSearch.getOrderStatus() != null) { Predicate status = cb.equal(o.get("status"), orderSearch.getOrderStatus()); criteria.add(status); } //회원 이름 검색 if (StringUtils.hasText(orderSearch.getMemberName())) { Predicate name = cb.like(m.<String>get("name"), "%" + orderSearch.getMemberName() + "%"); criteria.add(name); } cq.where(cb.and(criteria.toArray(new Predicate[criteria.size()]))); TypedQuery<Order> query = em.createQuery(cq).setMaxResults(1000); //최대 1000건 return query.getResultList(); } public List<Order> findAllWithMemberDelivery() { return em.createQuery( "select o from Order o" + " join fetch o.member m" + " join fetch o.delivery d", Order.class) .getResultList();} public List<OrderSimpleQueryDto> findOrderDtos() { return em.createQuery( "select new jpabook.jpashop.repository.order.simplequery.OrderSimpleQueryDto(o.id, m.name, o.orderDate, o.status, d.address)" + " from Order o" + " join o.member m" + " join o.delivery d", OrderSimpleQueryDto.class) .getResultList(); }} package jpabook.jpashop.repository;import jpabook.jpashop.domain.Address;import jpabook.jpashop.domain.OrderStatus;import lombok.Data;import java.time.LocalDateTime;@Data public class OrderSimpleQueryDto { private Long orderId; private String name; private LocalDateTime orderDate; private OrderStatus orderStatus; private Address address; public OrderSimpleQueryDto(Long orderId, String name, LocalDateTime orderDate, OrderStatus orderStatus, Address address) { this.orderId = orderId; this.name = name; this.orderDate = orderDate; this.orderStatus = orderStatus; this.address = address; } } 2022-05-31 02:13:36.433 ERROR 1563 --- [nio-8080-exec-4] o.h.hql.internal.ast.ErrorTracker : Unable to locate class [jpabook.jpashop.repository.order.simplequery.OrderSimpleQueryDto] [cause=org.hibernate.boot.registry.classloading.spi.ClassLoadingException: Unable to load class [jpabook.jpashop.repository.order.simplequery.OrderSimpleQueryDto]] 2022-05-31 02:13:36.436 ERROR 1563 --- [nio-8080-exec-4] o.h.hql.internal.ast.ErrorTracker : Unable to locate class [jpabook.jpashop.repository.order.simplequery.OrderSimpleQueryDto] [cause=org.hibernate.boot.registry.classloading.spi.ClassLoadingException: Unable to load class [jpabook.jpashop.repository.order.simplequery.OrderSimpleQueryDto]] org.hibernate.hql.internal.ast.DetailedSemanticException: Unable to locate class [jpabook.jpashop.repository.order.simplequery.OrderSimpleQueryDto] at org.hibernate.hql.internal.ast.tree.ConstructorNode.resolveConstructor(ConstructorNode.java:177) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.ast.tree.ConstructorNode.prepare(ConstructorNode.java:144) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.ast.HqlSqlWalker.processConstructor(HqlSqlWalker.java:1271) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectExpr(HqlSqlBaseWalker.java:2409) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectExprList(HqlSqlBaseWalker.java:2275) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectClause(HqlSqlBaseWalker.java:1534) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:611) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:339) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:287) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:276) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:192) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:636) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:748) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:848) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:114) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na] at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:362) ~[spring-orm-5.3.19.jar:5.3.19] at com.sun.proxy.$Proxy110.createQuery(Unknown Source) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na] at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:311) ~[spring-orm-5.3.19.jar:5.3.19] at com.sun.proxy.$Proxy110.createQuery(Unknown Source) ~[na:na] at jpabook.jpashop.repository.OrderRepository.findOrderDtos(OrderRepository.java:105) ~[classes/:na] at jpabook.jpashop.repository.OrderRepository$$FastClassBySpringCGLIB$$9808961b.invoke(<generated>) ~[classes/:na] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.19.jar:5.3.19] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.19.jar:5.3.19] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.19.jar:5.3.19] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.19.jar:5.3.19] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.19.jar:5.3.19] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.19.jar:5.3.19] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.19.jar:5.3.19] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.19.jar:5.3.19] at jpabook.jpashop.repository.OrderRepository$$EnhancerBySpringCGLIB$$3bdf9949.findOrderDtos(<generated>) ~[classes/:na] at jpabook.jpashop.api.OrderSimpleApiController.ordersV4(OrderSimpleApiController.java:70) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.19.jar:5.3.19] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.19.jar:5.3.19] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.19.jar:5.3.19] at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.62.jar:4.0.FR] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.19.jar:5.3.19] at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.62.jar:4.0.FR] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.19.jar:5.3.19] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.19.jar:5.3.19] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.19.jar:5.3.19] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.19.jar:5.3.19] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.19.jar:5.3.19] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.19.jar:5.3.19] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na] 2022-05-31 02:13:36.441 ERROR 1563 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate class [jpabook.jpashop.repository.order.simplequery.OrderSimpleQueryDto] [select new jpabook.jpashop.repository.order.simplequery.OrderSimpleQueryDto(o.id, m.name, o.orderDate, o.status, d.address) from jpabook.jpashop.domain.Order o join o.member m join o.delivery d]; nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate class [jpabook.jpashop.repository.order.simplequery.OrderSimpleQueryDto] [select new jpabook.jpashop.repository.order.simplequery.OrderSimpleQueryDto(o.id, m.name, o.orderDate, o.status, d.address) from jpabook.jpashop.domain.Order o join o.member m join o.delivery d]] with root cause org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate class [jpabook.jpashop.repository.order.simplequery.OrderSimpleQueryDto] [select new jpabook.jpashop.repository.order.simplequery.OrderSimpleQueryDto(o.id, m.name, o.orderDate, o.status, d.address) from jpabook.jpashop.domain.Order o join o.member m join o.delivery d] at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.ast.ErrorTracker.throwQueryException(ErrorTracker.java:93) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:282) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:192) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:636) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:748) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:848) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:114) ~[hibernate-core-5.6.8.Final.jar:5.6.8.Final] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na] at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:362) ~[spring-orm-5.3.19.jar:5.3.19] at com.sun.proxy.$Proxy110.createQuery(Unknown Source) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na] at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:311) ~[spring-orm-5.3.19.jar:5.3.19] at com.sun.proxy.$Proxy110.createQuery(Unknown Source) ~[na:na] at jpabook.jpashop.repository.OrderRepository.findOrderDtos(OrderRepository.java:105) ~[classes/:na] at jpabook.jpashop.repository.OrderRepository$$FastClassBySpringCGLIB$$9808961b.invoke(<generated>) ~[classes/:na] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.19.jar:5.3.19] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.19.jar:5.3.19] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.19.jar:5.3.19] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.19.jar:5.3.19] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.19.jar:5.3.19] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.19.jar:5.3.19] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.19.jar:5.3.19] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.19.jar:5.3.19] at jpabook.jpashop.repository.OrderRepository$$EnhancerBySpringCGLIB$$3bdf9949.findOrderDtos(<generated>) ~[classes/:na] at jpabook.jpashop.api.OrderSimpleApiController.ordersV4(OrderSimpleApiController.java:70) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.19.jar:5.3.19] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.19.jar:5.3.19] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.19.jar:5.3.19] at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.62.jar:4.0.FR] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.19.jar:5.3.19] at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.62.jar:4.0.FR] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.19.jar:5.3.19] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.19.jar:5.3.19] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.19.jar:5.3.19] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.19.jar:5.3.19] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.19.jar:5.3.19] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.19.jar:5.3.19] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na] 오류내용은 이러합니다. OrderSimpleApiController 클래스에 @GetMapping("/api/v4/simple-orders")public List<OrderSimpleQueryDto> ordersV4() { return orderRepository.findOrderDtos();} orderRepository 가 잘못된 것일까요?.. 오류 내용을 보면 저 부분을 얘기하는 것 같은데 어떤 부분이 잘못되었는지 이해가 잘 안됩니다 ㅜㅠ 도움 부탁드립니다!!!!..
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
postman사용법
안녕하세요! 현재 회원등록 api 강의를 듣고 있는 중인데 postman 설치 하여 사용하는 내용이 나옵니다. postman 처음 사용 과정은 따로 강의로 들을 수 있는게 없나요?! 스프링부트와 jap활용1 강의를 듣고 바로 넘어왔는데 내용이 따로 없어서요!!! ㅜㅜㅜ headers 부분에 Content-Type 은 직접 입력해서 넣었구요 .. body에 내용을 넣어 send를 했는데 밑에 내용처럼 오류?가 뜹니다 ㅠㅠ 무슨 문제일까요?