inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

172만명의 커뮤니티!! 함께 토론해봐요.

Array.sort 사용 구분

미해결

자바(Java) 알고리즘 문제풀이 입문: 코딩테스트 대비

앞 문제에서 Collection.sort를 쓰면 문제에서 효율적이지 못하다는 댓글을 봐서 처음부터 Array.sort를 해서 정렬하는 방법을 생각을 못했는데 어떤 문제에선 사용하고 사용하지말고 구분이잘 안되는데 이럴땐 어떻게 하나요...

  • java
  • 코딩-테스트
이주용 댓글 1 좋아요 0 조회수 385

flush() 와 clear()

해결됨

실전! 스프링 데이터 JPA

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 1. 스프링 데이터 JPA 가 지원하는 save를 호출하면 flush()가 나가는건가요 아니면 save를 하고 bulkAgePlus()를 호출하면서 bulkAgePlus() 에 있는 JQPL이 실행되서 flush() 가 나가는건가요 ? bulkAgePlus()를 실행하면 JPQL 실행이되고, JPQL 이 실행이 되면 flush() 가 호출이 되는데 이때 SQL쿼리문이 DB에 전송이대서 DB에는 업데이트가 되어있지만 영속성 컨텍스트는 업데이트가 안되기 때문에 clear()를 해주는게 맞는건가요 ?

  • java
  • spring
  • spring-boot
  • jpa
최재영 댓글 1 좋아요 0 조회수 482

CRUD에 따른 ResponseDto를 보내는 유형 및 ResponseDto 구성 방식에 대한 질문

미해결

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

안녕하십니까 영한님. 영한님 덕분에 JAVA Spring 기반 백엔드 개발의 시작을 할 수 있었고, 이제는 5개월 차 스타트업 백엔드 개발자로써 커리어를 시작하게 되었습니다. 현업에 와서는 오히려 취준생 때 보다 더 많은 고민을 하게 되느데요, 질문 1. 그중 최근에 CRUD의 각 상황별 API 응답을 어떻게 보내는게 적절할지, 질문 2. 그리고 ResponseDto를 어떻게 구성하는것이 적절할지에 대한 고민을 팀장님과 함께 하고있어서, 영한님의 생각을 여쭙고자 질문글을 올리게 되었습니다. 답변 해주시면 정말 감사할 거 같습니다! Q1. 생성, 조회 , 수정, 삭제 API의 응답을 각각 어떻게 보내시는지 여쭤보고 싶습니다. 가장 먼저 조회의 경우는 말 그대로 path의 Entity 및 관련된 Entity 정보를 조합하여 응답 DTO로 변환하여 보내고 있습니다. 그런데 나머지 Write Operation에 대한 응답을 어디까지 보내야 하냐가 이슈 입니다. 예를들면 엔티티의 생성의 경우 엔티티의 응답 DTO를 보내면 - 프론트에서 별도의 조회 API 호출 없이 바로 프론트가 화면에 뿌려줄 수 있으니깐 저는 생성의 경우에도 조회와 마찬가지로 Entity의 정보를 조합하여 응답 DTO로 변환하여 보내고 있었습니다. 그런데 이러한 부분이 Command Query Sperate 원칙에 어긋나는것 같아, 영한님께서는 혹시 생성한 Entity의 Key만 보내시는지, 아니면 Entity의 정보를 DTO로 변환하여 보내시는지 궁금합니다. 만약 Entity의 Id만 보내신다면 이후에 별도로 조회API를 호출해야 하고 그 또한 비용일텐데 이러한 부분은 어떻게 하시는지 여쭤보고 싶습니다. 이제 수정 API인데요, 제가 다룬 비즈니스 로직의 경우 수정 비즈니스 로직이 다양하고 , 각 비즈니스 로직의 경우 다뤄지는 Entity의 종류가 다른 경우였습니다. (중심 Entity는 동일하지만, 연관된 Entity를 누구까지 건드리냐의 차이) 그래서 하나의 통일된 응답으로 보내기 모호한 점이 첫 번째 이유이고, 애초에 수정 후에 프론트 화면에서 그 엔티티의 정보를 보여줄 필요가 없어서 라는 두번째 이유에 의해서 에초에 엔티티의 Id값도 보내지 않고 있었는데요, 이 수정 API의 응답을 영한님은 어떻게 진행하지는지 그 이유가 궁금합니다. 마지막으로 삭제의 경우는 정말, 프론트에게 보낼 응답이 없어도 되는 경우 라고 생각했는데요, 팀장님의 의견은 만약에 나중에 삭제한 Entity를 복구하는 요구사항이 추가되는것을 고려하여 Id 정도는 넘기자는 의견을 내어주셨습니다. 마찬가지로 삭제의 경우도 어떤식으로 수행하시는지 그 이유가 궁금합니다. Q3. 마지막으로 Entity의 ResponseDto의 필드를 어떤식으로 구성하시는지 궁금합니다 예를들면 저의 경우는 API는 프론트와 서버 간의 스펙이라고 생각하고, Entity의 단건조회의 경우는 단건 조회용 ResponseDto를, 전체조회의 경우는 전체 조회용 SummaryResponseDto를 별도로 만들어서 사용하고 있었습니다. 저희 팀장님 께서는 프론트쪽도 일을 해오시다가 , 백엔드쪽 분야로 전향하신 케이스 인데요, 그렇다 보니 어떻게 해야 프론트의 생산성이 올라가는지를 고려하시는 분이셨고, 팀장님의 생각은 서버에서 넘겨주는 응답에 일관성이 있어야 그 응답을 사용하는 프론트 측도 학습이 되고 놓치는 부분 없이 생산성이 올라간다 는 의견이셨습니다. 그래서 Entity별로 당장 사용하지 않더라도 가능한 모든 필드를 담은 ResponseDto를 하나만 만들고, 해당 ResponseEntity의 조합으로 각 API별 응답 Dto를 만들어서 사용하면 , 프론트 측 에서는 일관성 있는 응답값을 사용할 수 있다는 의견이셨습니다. 물론 이 방법이 네트워크 패킷의 양을 쓸데없이 증가시킨다는 것을 알고 계시면서도, 생산성에 큰 영향을 미치는 부분이라고 생각하셨습니다. 예를들어 다음과 같이 각 Entity의 응답 Dto의 조합별로 API의 ResponseDto를 만들 수 있습니다. ResponseDto{ UserDto{ id : 1, name : “aaa” … // User엔티티의 거의 모든 필드 } ItemDto{ id : 2, name : “bbb”, … // Item엔티티의 거의 모든 필드 } } 저는 이러한 부분에 대해 생각해 본 적이 없이, 그냥 제가 “해당 API를 호출하는 화면에서 필요한 정보들만을 담아 (혹은 여러 화면에서 쓰인다면 여러개를 고려) ResponseDto를 각각 만들어서” 넘겼는데요 영한님께서는 이러한 ResponseDto를 구성하는 부분에 있어서 상황별로 필드를 재구성 하여 ResponseDto를 정의하여 사용하시는 편 인지 (SummaryResponseDto 등의 별도 Dto에 사용될 Entity의 필드들을 풀어서 정의하시는지) 아니면 생산성을 고려하여 각 Entity별 Dto를 만들고, 이들을 조합하여 ReponseDto를 정의하시는 편 이신지 , 혹은 다른 규칙이 있으신지 궁금합니다. 물론 그렇다고 , 팀장님의 의견에서 전체조회시 사용하는 DTO와 단건조회시 사용하는 DTO가 동일하더라도, 전체조회 후 단건조회를 할때 단건조회 API를 호출하지 말고 기존 Front가 가지고 있는 값을 쓰지는 말자는 의견 이십니다 (단건조회API는 별도로 호출해야 한다) 그저 핵심은 프론트가 다루는 ResponseDto의 일관성을 위해서 입니다 (결론은 생산성을 위해) 긴글 읽어주셔서 감사합니다. 항상 건강하셨으면 좋겠고, 다음 강의들도 손꼽아 기다리고 있습니다!

  • java
  • spring
  • spring-boot
  • jpa
요니 댓글 3 좋아요 0 조회수 1440

jpql 엔티티 인지 오류

미해결

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 일단은 해결 했습니다. findAllString 이용하는데 Order를 얘가 모르는 거 같아서.. String jpql = "select o From jpabook.jpashop.domain.Order o join o.member m"; 이렇게 패키지경로까지 다 명시해줬더니 인지를 하더라구요.. 안 그러면 org.hibernate.query.sqm.UnknownEntityException: Could not resolve root entity 'Order' at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitRootEntity(SemanticQueryBuilder.java:1960) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitRootEntity(SemanticQueryBuilder.java:253) ~[hibernate-core-6.2.13.Final.jar:6.2.13.Final] ............... 얘가 이렇게 Order 인지 못한다고 오류가 뜹니다.. 원래 엔티티는 그냥 @Entity 등록 하면 알아서 인지 되는걸로 알고 있었는데.. 왜 이런 걸까요? package jpabook.jpashop.domain; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @Entity(name = "orders") @Getter @NoArgsConstructor(access = AccessLevel.PUBLIC) public 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 LocalDateTime orderDate; @Enumerated(EnumType.STRING) private OrderStatus status; public void changeMember(Member member){ this.member = member; member.getOrders().add(this); } public void addOrderItem(OrderItem orderItem){ orderItems.add(orderItem); orderItem.setOrder(this); } private void setOrderDate(LocalDateTime orderDate) { this.orderDate = orderDate; } public void changeDelivery(Delivery delivery){ this.delivery = delivery; delivery.setOrder(this); } private void setStatus(OrderStatus status) { this.status = status; } public static Order createOrder(Member member, Delivery delivery, OrderItem... orderItems){ Order order = new Order(); order.changeMember(member); order.changeDelivery(delivery); for (OrderItem orderItem : orderItems) { order.addOrderItem(orderItem); } order.setStatus(OrderStatus.ORDER); order.setOrderDate(LocalDateTime.now()); return order; } public void cancel(){ if(delivery.getStatus() == DeliveryStatus.COMP){ throw new IllegalStateException("이미 배송완료된 상품은 취소가 불가능합니다."); } this.setStatus(OrderStatus.CANCEL); for (OrderItem orderItem : orderItems) { // orderItem.getItem().removeStock(orderItem.getCount()); orderItem.cancel(); } } public int getTotalPrice(){ int totalPrice = 0; for( OrderItem orderItem : orderItems){ totalPrice += orderItem.getTotalPrice(); } return totalPrice; } }

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
궁금이 댓글 1 좋아요 0 조회수 2889

MemberForm은 이미 모델에 들어가 있는거죠?

해결됨

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 검증오류가 날 시 BindingResult에 의해 들어가는 게 아니라, 저렇게 인자로 받는 건 이미 모델에 들어가 주는거죠?

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
궁금이 댓글 1 좋아요 0 조회수 384

Spring Security 6.0 이상 (Spring boot 3.0 이상)에서 다중 config 설정 방법

미해결

스프링 시큐리티

안녕하세요 이렇게 좋은 Spring Security에 애를 많이 먹던 도중 늦게나마 열심히 듣고 있는 사람입니다. 강의를 들으면서 Spring Security 6.0 이상 버전으로 혼자 마이그레이션 해보며 공부를 진행하는데요.. 다른 분들은 모르겠지만 저는 6.0 이상 버전에서의 다중 보안 설정에서 애를 좀 먹어서.. 혹시나 저 같으신 분들이 있으실까봐 글을 남깁니다..! 다름이 아니라 Spring Security 6.0 이상 버전에서는 먼저 오버라이드해서 함수를 구현하는 것이 아니라 컴포넌트화 시켜서 진행합니다. 또한 HttpSecurity 안의 내용을 구현하는데 변경점이 있다는 것이 가장 큰 차이점인 것 같습니다. 예를 들어 UserSecurityConfig, AdminSecurityConfig를 만들어서 각 경우에 따라 다른 설정을 적용하고 싶은 경우에 두 가지의 config 파일을 만들 수 있다고 가정하면.. 저의 경우에는 AdminSecurityConfig에서 지정한 부분이 권한 정보에 따라 접근이 막히지 않고 다 접근이 가능한 ("/admin/pay"를 user가 접근 가능) 상황이었습니다. 뭐가 문제인지 한참을 찾던 도중 https://docs.spring.io/spring-security/reference/servlet/configuration/java.html 공식 문서를 통해 답을 찾았습니다. 간략하게 해결법부터 말씀드리자면 path로 접근 제한을 하는 경우에 http.securityMatcher()를 사용해야 한다는 점 입니다. 이렇게 하면 아주 잘 구분이 되더군요..! 혹시나 저처럼 하시는 분이 계실까봐 남깁니다..! @Bean @Order(0) public SecurityFilterChain adminFilterChain(HttpSecurity http) throws Exception{ http .securityMatcher("/admin/pay") .authorizeHttpRequests(request -> request.anyRequest().hasRole("ADMIN")); return http.build(); } @Bean @Order(1) public SecurityFilterChain systemFilterChain(HttpSecurity http) throws Exception{ http .securityMatcher("/admin/**") .authorizeHttpRequests(request -> request .anyRequest().hasAnyRole("SYS", "ADMIN")); return http.build(); } @Bean @Order(2) public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{ http .authorizeHttpRequests(request -> request .requestMatchers(antMatcher("/user/**")).hasRole("USER") .anyRequest().authenticated());

  • java
  • spring-boot
  • spring-security
jwl5015 댓글 3 좋아요 4 조회수 3375

named lock vs 비관적 락

미해결

재고시스템으로 알아보는 동시성이슈 해결방법

좋은 강의 너무 감사합니다. 강의를 보며 궁금한 점이 생겨서 질문 드립니다. named lock을 통해 동시성 문제를 해결하는 예시를 보았을 때, 비관적 락과 무엇이 다른 것인지 큰 차이를 느끼지 못했습니다. named lock이 비관적 락에 비해 가지는 장단점에 비해 찾아보니, timeout 설정이 좀 더 간편하다는 내용 말고는 유의미한 차이를 찾지 못했습니다. (그러나 비관적 락 + queryhint 를 사용하면 비관적 락 사용 시에도 딱히 어려움 없이 timeout을 설정할 수 있었습니다.) 혹시 named lock이 비관적 락에 비해 지니는 장단점과, 어떤 경우에 비관적 락 대신 Named lock을 통해 분산락을 구현하시는지 궁금하여 질문드립니다.

  • java
  • spring
  • 동시성
신동훈 댓글 1 좋아요 0 조회수 1426

SpringPhysicalNamingStrategy 바뀐건가요?

해결됨

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 찾아도 안나오는데 CamelCaseToUnderscoresNamingStrategy 이걸로 바뀐 것 같네요.

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
궁금이 댓글 3 좋아요 0 조회수 1456

정적 팩토리 메서드에 static이 붙어야 하는 이유

미해결

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

안녕하세요. 강의 잘 보고 있습니다! 다른 분 질문에 궁금한 것이 해소되지 않아 질문드립니다. https://www.inflearn.com/course/lecture?courseSlug=%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-JPA-%ED%99%9C%EC%9A%A9-1&unitId=24297&category=questionDetail&q=30892&tab=community 정적 팩토리 메소드 사용 이유중에 static 메모리에 올라가기때문에 새로운 객체를 생성하지 않는 장점이 있는 거라고 알고 있습니다. 이 예제의 경우 static을 빼도 JPA가 엔티티로 관리하면서 어차피 사용할 수 있는 부분아닌가요..? 라는 질문에서 강사님께서는 static을 빼보면 이해될 거라고 답변하셨습니다. 제가 생각하기로는 정적 팩토리 메서드 안에서 생성자를 통해 인스턴스를 생성하는 것은 똑같아 보이고, 호출할 때 new가 아닌 Order.createOrder()로 호출하는 것 외에는 차이점을 못 느꼈습니다. 조금 더 상세한 가르침을 주시면 감사하겠습니다!

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
저스트 댓글 2 좋아요 1 조회수 1132

Querydsl SQLExpressions에 listagg 관련 질문

미해결

안녕하세요, 김영한 님. Querydsl SQLExpressions에 listagg 관련하여 질문이 있습니다. 현재 Projections.constructoer 방식으로 조회한 결과를 Dto로 받고있는데요, SQLExpressions.listagg(컬럼, ",").withinGroup().orderBy(컬럼).getValue().as("listaggs") 로 select후 Dto에서 String으로 못받는데 String으로 받으려면 어떻게 해야 될까요? 방법이 없는걸까요? 이미 같은 질문을 남긴 글이 있는데 미해결 상태라 다시 한번 글 올려 봅니다. 이방법을 사용하는 이유는 A 테이블, B 테이블이 있는데 1:N의 관계 입니다) A테이블 조회시 Response에는 B테이블의 컬럼 하나도 추가로 목록에 보여줘야 하는데 그럴때 B테이블의 해당 컬럼의 값이 다른 데이터가 2개 이상일시 A정보가 2건이 나오게 되서 (페이징 처리시에도 총 카운트와 페이징 처리가 제대로 되지 않습니다.) 한 row로 보여지게 하기 위해 사용하려 Querydsl SQLExpressions에 listagg 사용하려는데, String으로 받을수가 없더군요... 혹 Querydsl SQLExpressions에 listagg 아니더라도 다른 방법이 있을까요?

  • jpa
  • querydsl
  • java
skyghy3342 댓글 1 좋아요 0 조회수 1027

deleteUser 관련 질문

미해결

자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]

현재 코드에서는 name을 기준으로 delete를 하는데요, findByName(name)을 이용한 코드에서 DB 안에 같은 이름의 회원이 2명 이상인 경우엔 오류가 생깁니다. 그 이유가 find는 return 개수가 1건이기 때문에 rollback 된다고 생각했습니다. 이 버그를 수정하기 위해서 deleteUser의 파라미터는 Long id 로 수정했는데, 또 안 되더라고요...? findAll을 쓰면 같은 이름을 가진 모든 회원이 삭제될 것 같고... 어떻게 하면 동명이인의 회원 중에서 내가 원하는 한 회원만 삭제할 수 있나요? + 추가 방금 다른 학생분의 질문과 답변을 읽었습니다. 같은 내용의 질문인 것 같네요! 그러면 파라미터를 Long id 로 변경하되, 현재 실습 중인 UI에서도 코드를 수정해야하는 부분이 있기에 삭제가 안 되는 게 맞다고 이해하면 될까요?

  • java
  • spring
  • aws
  • mysql
  • spring-boot
  • jpa
alstjs 댓글 1 좋아요 1 조회수 227

트랜잭션 전파속성, 데이터 소스

해결됨

재고시스템으로 알아보는 동시성이슈 해결방법

안녕하세요. 강의 잘 보고 있습니다. 의문이 생겨 질문을 남깁니다. 트랜잭션 전파속성을 REQUIRES_NEW로 해서 새로 생성한 이유가 있을까요? 그냥 REQUIRED로 하면 안되나요?? 강의 내에서 데이터소스를 분리하는 것을 추천해주셨는데, 커넥션 풀 사이즈를 늘리면 안되나요?? 감사합니다.

  • java
  • spring
  • 동시성
rhkdals195 댓글 2 좋아요 0 조회수 665

Naver Login시 권한에 대해 질문이 있습니다

미해결

스프링 시큐리티 OAuth2

CustomAuthorityMapper 클래스에서 강사님과 코드는 동일하나 authorities가 넘어올시에 위와 같이 넘어옵니다. 그래서 강사님 영상과 다르게 ROLE_USER만이 authority에 대해서 담기게 되고 위의 사진은 hasRole 권한을 해제하여 찍어본것입니다. /api/user에 진입이 불가합니다 코드는 동일한데 뭐가 문제일까요,,,? 강사님의 네이버 로그인시는 response를 안벗기고도 진입이 가능해서 질문드립니다 package io.security.oauth2.sociallogin; import lombok.RequiredArgsConstructor; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; import java.util.Collection; import java.util.HashSet; import java.util.Set; public class CustomAuthorityMapper implements GrantedAuthoritiesMapper { private String prefix = "ROLE_"; @Override public Set<GrantedAuthority> mapAuthorities(Collection<? extends GrantedAuthority> authorities) { HashSet<GrantedAuthority> mapped = new HashSet<>(authorities.size()); for (GrantedAuthority authority : authorities) { mapped.add(mapAuthority(authority.getAuthority())); } return mapped; } private GrantedAuthority mapAuthority(String name) { if(name.lastIndexOf(".") > 0){ int index = name.lastIndexOf("."); name = "SCOPE_" + name.substring(index+1); } if (!this.prefix.isEmpty() && !name.startsWith(this.prefix)) { name = this.prefix + name; } return new SimpleGrantedAuthority(name); } }

  • java
  • spring
  • spring-boot
  • oauth
hangs0908 댓글 2 좋아요 0 조회수 590

일대다 패치 조인 사용 시, 뻥튀기가 되지 않는 문제

미해결

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] 아래 처럼 print를 찍었을 때, 저는 id 1과 2가 두 개가 나오지 않습니다. 관련 코드는 아래 첨부하겠습니다. 강의대로 똑같이 했는데, 왜 1개씩만 나오는지 모르겠습니다.. distinct를 넣었을 때와 안넣었을때의 결과가 같습니다. DB에서는 4개로 나오는데 Postman이랑 콘솔에서는 2개로 난오네요.. [v3 적용 시] package jpabook.jpashop2.api; import jpabook.jpashop2.domain.Address; import jpabook.jpashop2.domain.Order; import jpabook.jpashop2.domain.OrderItem; import jpabook.jpashop2.domain.OrderStatus; import jpabook.jpashop2.repository.OrderRepository; import jpabook.jpashop2.repository.OrderSearch; import lom bok.Data; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.time.LocalDateTime; import java.ut il.List; import java.util.stream.Collector s; import stati c java.util.stream.Collectors. toList ; @RestController @RequiredArgsConstructor public class OrderApiController { private final OrderRepository orderRepository; @GetMapping("/api/v1/orders") public List<Order> ordersV1(){ List<Order> all = orderRepository.findAllByString(new OrderSearch()); for (Order order : all) { order.getMember().getName(); // 프록시 객체 초기화 order.getDelivery().getAddress(); List<OrderItem> ord erItems = order.g etOrderItems(); orderItems.stream().forEach(o -> o.getItem().getName()); } return all; } @GetMapping("/api/v2/orders") public List<OrderDto> ordersV2(){ List<Order> orders = orderRepository.findAllByString(new OrderSearch() ); List<OrderDto> collect = orders.stream() .map(o -> new OrderDto(o)) .collect( toList ()); return collect; } @GetMapping("/api/v3/orders") public List<OrderDto> ordersV3(){ List<Order> orders = orderRepository.findAllWithItem(); for (Order order : orders) { System. out .println("order ref= " + order + " id=" + o rder.getId()); } List<OrderDto> collect = orders.stream() .map(o -> new OrderDto(o)) .collect( toList ()); return collect; } @Data static class OrderDto{ private Long orderId; private String name; private LocalDateTime orderDate; private OrderStatus orderStatus; private Address address; // VO는 그대로 사용해도 되지만, (VO는 객체이기 때문에, 안에 값이 변하면 다른 객체로 판단) private List<OrderItemDto> orderItems; // 엔티티는 DTO로 다시 한번 래핑이 필요하다. public OrderDto(Order order) { orderId = order.getId(); name = order.getMember().getName(); orderDate = order.getOrderDate(); orderStatus = order.getStatus(); address = order.getDelivery().getAddress(); orderItems = order.getOrderItems().stream() .map(orderItem -> new OrderItemDto(orderItem)) .collect( toList ()); } } @Data static class OrderItemDto { // OrderItem에서 필요한 값만 다시 추출 private String itemName; // 상품명 private int orderPrice; // 주문 가격 private int count; // 주문 수량 public OrderItemDto(OrderItem orderItem) { itemName = orderItem.getItem().getName(); orderPrice = orderItem.getOrderPrice(); count = orderItem.getCount(); } } } public List<Order> findAllWithItem() { return em.createQuery("select o from Order o" + " join fetch o.member m" + " join fet ch o.deliv ery d" + " join fetch o.orderItems oi" + " join fetch oi.item i", Order.class) .getResultList(); }

  • java
  • spring
  • spring-boot
  • jpa
rr8602 댓글 1 좋아요 3 조회수 1041

결과 쿼리 개수가 맞지 않아서 문의 드립니다.

미해결

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] [간단한 주문 조회 V3: 엔티티를 DTO로 변환 -패치 조인 최적화] 강의에서 5분 50초 쯤에 v2를 돌려봤을 때, 강사님은 쿼리가 5번 나오는데, 저는 계속 7번이 나오더라구요... order가 처음에 주문 2개를 만들어서 이미 영속성 상태라 그 다음에는 1차 캐시에서 가져오는 것으로 보여 쿼리는 생성이 안되어야 한다고 생각이 드는데, 왜 계속 order 쿼리가 2번 더 나오는 걸까요...? [Query] 2023-10-25T21:54:33.448+09:00 DEBUG 37176 --- [nio-8080-exec-3] org.hibernate.SQL : select o1_0.order_id, o1_0.deliver_id, o1_0.member_id, o1_0.order_date, o1_0.status from orders o1_0 join member m1_0 on m1_0.member_id=o1_0.member_id fetch first ? rows only 2023-10-25T21:54:33.449+09:00 INFO 37176 --- [nio-8080-exec-3] p6spy : #1698238473449 | took 0ms | statement | connection 11| url jdbc:h2:tcp://localhost/~/jpashop2 select o1_0.order_id,o1_0.deliver_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 join member m1_0 on m1_0.member_id=o1_0.member_id fetch first ? rows only select o1_0.order_id,o1_0.deliver_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 join member m1_0 on m1_0.member_id=o1_0.member_id fetch first 1000 rows only; 2023-10-25T21:54:33.450+09:00 DEBUG 37176 --- [nio-8080-exec-3] org.hibernate.SQL : select m1_0.member_id, m1_0.city, m1_0.street, m1_0.zipcode, m1_0.name from member m1_0 where m1_0.member_id=? 2023-10-25T21:54:33.451+09:00 INFO 37176 --- [nio-8080-exec-3] p6spy : #1698238473451 | took 0ms | statement | connection 11| url jdbc:h2:tcp://localhost/~/jpashop2 select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=? select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=1; 2023-10-25T21:54:33.451+09:00 DEBUG 37176 --- [nio-8080-exec-3] org.hibernate.SQL : select d1_0.delivery_id, d1_0.city, d1_0.street, d1_0.zipcode, d1_0.status from delivery d1_0 where d1_0.delivery_id=? 2023-10-25T21:54:33.451+09:00 INFO 37176 --- [nio-8080-exec-3] p6spy : #1698238473451 | took 0ms | statement | connection 11| url jdbc:h2:tcp://localhost/~/jpashop2 select d1_0.delivery_id,d1_0.city,d1_0.street,d1_0.zipcode,d1_0.status from delivery d1_0 where d1_0.delivery_id=? select d1_0.delivery_id,d1_0.city,d1_0.street,d1_0.zipcode,d1_0.status from delivery d1_0 where d1_0.delivery_id=1; 2023-10-25T21:54:33.452+09:00 DEBUG 37176 --- [nio-8080-exec-3] org.hibernate.SQL : select o1_0.order_id, o1_0.deliver_id, o1_0.member_id, o1_0.order_date, o1_0.status from orders o1_0 where o1_0.deliver_id=? 2023-10-25T21:54:33.452+09:00 INFO 37176 --- [nio-8080-exec-3] p6spy : #1698238473452 | took 0ms | statement | connection 11| url jdbc:h2:tcp://localhost/~/jpashop2 select o1_0.order_id,o1_0.deliver_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 where o1_0.deliver_id=? select o1_0.order_id,o1_0.deliver_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 where o1_0.deliver_id=1; 2023-10-25T21:54:33.453+09:00 DEBUG 37176 --- [nio-8080-exec-3] org.hibernate.SQL : select m1_0.member_id, m1_0.city, m1_0.street, m1_0.zipcode, m1_0.name from member m1_0 where m1_0.member_id=? 2023-10-25T21:54:33.453+09:00 INFO 37176 --- [nio-8080-exec-3] p6spy : #1698238473453 | took 0ms | statement | connection 11| url jdbc:h2:tcp://localhost/~/jpashop2 select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=? select m1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name from member m1_0 where m1_0.member_id=2; 2023-10-25T21:54:33.453+09:00 DEBUG 37176 --- [nio-8080-exec-3] org.hibernate.SQL : select d1_0.delivery_id, d1_0.city, d1_0.street, d1_0.zipcode, d1_0.status from delivery d1_0 where d1_0.delivery_id=? 2023-10-25T21:54:33.454+09:00 INFO 37176 --- [nio-8080-exec-3] p6spy : #1698238473454 | took 0ms | statement | connection 11| url jdbc:h2:tcp://localhost/~/jpashop2 select d1_0.delivery_id,d1_0.city,d1_0.street,d1_0.zipcode,d1_0.status from delivery d1_0 where d1_0.delivery_id=? select d1_0.delivery_id,d1_0.city,d1_0.street,d1_0.zipcode,d1_0.status from delivery d1_0 where d1_0.delivery_id=2; 2023-10-25T21:54:33.454+09:00 DEBUG 37176 --- [nio-8080-exec-3] org.hibernate.SQL : select o1_0.order_id, o1_0.deliver_id, o1_0.member_id, o1_0.order_date, o1_0.status from orders o1_0 where o1_0.deliver_id=? 2023-10-25T21:54:33.454+09:00 INFO 37176 --- [nio-8080-exec-3] p6spy : #1698238473454 | took 0ms | statement | connection 11| url jdbc:h2:tcp://localhost/~/jpashop2 select o1_0.order_id,o1_0.deliver_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 where o1_0.deliver_id=? select o1_0.order_id,o1_0.deliver_id,o1_0.member_id,o1_0.order_date,o1_0.status from orders o1_0 where o1_0.deliver_id=2; [OrderSimpleApiController] package jpabook.jpashop2.api; import jpabook.jpashop2.Repository.OrderRepository; import jpabook.jpashop2.Repository.OrderSearch; import jpabook.jpashop2.domain.Address; import jpabook.jpashop2.domain.Order; import jpabook.jpashop2.domain.OrderStatus; import lomb ok.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 ja va.util.stream.Collectors; /** * X To One (컬렉션 X) * Order * Order -> Member * Order -> Delivery */ @RestController @RequiredArgsConstructor public 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개 List<Order> orders = orderRepository.findAllByString(new Order Search()); List<SimpleOrderDto> result = orders.stream() .map(o -> new SimpleOrderDto(o)) // map : a -> b로 치환 .collect(Collectors. toList ()); return result; } @GetMapping("/api/v3/simple-orders") public List<SimpleOrderDto> ordersV3() { List<Order> orders = orderRepository.findAll WithMemberDel ivery(); List<SimpleOrderDto> result = orders.stream() .map(o -> new SimpleOrderDto(o)) .collect(Collectors. toList ()); return result; } @Data static class SimpleOrderDto{ // API 명세서 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(); } } } [OrderRepository] ... public List<Order> findAllWithMemberDelivery() { return em.createQuery("select o from Order o" + " join fetch o.member m" + " join fet ch o.deliv ery d", Order.class) .getResultList(); }

  • java
  • spring
  • spring-boot
  • jpa
rr8602 댓글 2 좋아요 0 조회수 653

스프링 사용 중 생기는 오류

미해결

안녕하세요 spring tools4를 설치하였고 돌아가는지 확인하고 싶어 확인하는 도중에 오류가 걸려서 글 올립니다. java는 11로 사용하였고 demo1는 local로 실행했을 때 Exception in thread "main" java.lang.UnsupportedClassVersionError: org/springframework/boot/SpringApplication has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 55.0 오류가 떠서 java버전이 다르다는 것을 알기는 알아냈지만 인터넷으로 검색한 방법을 다 써봐도 해결이 안됐습니다. 사용한 방법은 build path에서 jre system library로 해보았고 installed jres도 제대로 해두었습니다. compiler에도 11로 표시하였는데 혹시 다른 추가적이 방법이 있을까요

  • spring
  • java
  • springboot
박수현 댓글 1 좋아요 0 조회수 888

내용정리 화면은 어디서 볼수있나요?

미해결

스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

화면에서 보여주시는 내용정리된 노트?는 어디서 볼수있나요?

  • java
  • spring
  • mvc
  • spring-boot
박예슬 댓글 0 좋아요 0 조회수 737

h2 버그인가요?

해결됨

자바 ORM 표준 JPA 프로그래밍 - 기본편

[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 저는 ddl auto를 create로 하고 시퀀스 전략 했을 때, persist 안하고 봐도 시퀀스가 그냥 1, 증가가 50입니다.. 그 다음 persist를 한번 해 봤더니, next value for member_seq를 한번만 호출했습니다. 근데 persist 2번 이상하면, next value for member_seq를 2번 호출합니다. 시퀀스의 현재값도 101번이 됩니다. 뭔가 JPA쪽에서 놓친건가요..? 아니면 제가 뭔가 강의에서 놓친건가요? 그렇게 현재값 101번 만든 후, 이번엔 dll.auto 를 none으로 해서 다시 돌려봤더니 다서 persist 해서 테이블에 저장해서 나온 건 52부터 찍힙니다. persist 안한 것 persist 1번 next value for member_seq 한번 호출 persist 2번 호출 next value for member_seq가 두번 호출 됍니다. 그런데.. 이 상태에서 ddl.auto 를 none으로 하고 다시 한번 로직을 실행해 봤더니.. 어.. 제 생각이 맞다면 101부터 id가 매겨져야 할 것 같은데.. 어.. public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello"); EntityManager em = emf.createEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); try{ Member member1 = new Member(); member1.setUsername("A"); Member member2 = new Member(); member2.setUsername("B"); Member member3 = new Member(); member3.setUsername("C"); em.persist(member1); em.persist(member2); // em.persist(member3); tx.commit(); } catch (Exception e){ tx.rollback(); } finally { em.close(); } emf.close(); } 사용 버전 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>jpa-basic</groupId> <artifactId>ex-hello-jpa</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.hibernate.orm</groupId> <artifactId>hibernate-core</artifactId> <version>6.2.9.Final</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>2.1.214</version> </dependency> </dependencies> </project>

  • java
  • jpa
궁금이 댓글 3 좋아요 1 조회수 965

선생님 (!morning) 부분 질문이 있습니다!

미해결

나도코딩의 자바 기본편 - 풀코스 (20시간)

boolean morningCoffee= false if(!morningCoffee){ sout(아이스아메리카노 +!) } sout(주문완료) 논리부정연산자로 !morningCoffee == true 가 되는데 morningCoffee가 false가 맞을때 라고 이해해도 될까요? 헷갈려서 질문남깁니다~!

  • java
가진빵다내놔 댓글 1 좋아요 0 조회수 247

인기 태그

인프런 TOP Writers

주간 인기글