묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨실무 환경 그대로 주문게시판 만들기 웹개발 기초 마스터
별첨 자료가 어디있는지요
안녕하세요 강의를 수강하고 있습니다. 별첨 자료에 쿼리랑 참고하려고 하는데 별첨자료 파일이 어디있는지 못찾겠어서 경로 알려주시면 감사드립니다.
-
미해결재고시스템으로 알아보는 동시성이슈 해결방법
named lock vs 비관적 락
좋은 강의 너무 감사합니다.강의를 보며 궁금한 점이 생겨서 질문 드립니다. named lock을 통해 동시성 문제를 해결하는 예시를 보았을 때, 비관적 락과 무엇이 다른 것인지 큰 차이를 느끼지 못했습니다.named lock이 비관적 락에 비해 가지는 장단점에 비해 찾아보니, timeout 설정이 좀 더 간편하다는 내용 말고는 유의미한 차이를 찾지 못했습니다.(그러나 비관적 락 + queryhint 를 사용하면 비관적 락 사용 시에도 딱히 어려움 없이 timeout을 설정할 수 있었습니다.) 혹시 named lock이 비관적 락에 비해 지니는 장단점과, 어떤 경우에 비관적 락 대신 Named lock을 통해 분산락을 구현하시는지 궁금하여 질문드립니다.
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
SpringPhysicalNamingStrategy 바뀐건가요?
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]찾아도 안나오는데 CamelCaseToUnderscoresNamingStrategy 이걸로 바뀐 것 같네요.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
정적 팩토리 메서드에 static이 붙어야 하는 이유
안녕하세요. 강의 잘 보고 있습니다! 다른 분 질문에 궁금한 것이 해소되지 않아 질문드립니다.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 테스트를 추가하고 싶은 개발자들의 오답노트
List<Domain> -> List<Response> 변환을 Controller에서 하는 게 맞나요?
Domain -> Response 변환 코드를 Domain에 정의해두고Controller에서 Domain 메서드를 호출해서 Response를 변환하는게 맞나는 건 이해했습니다. 근데 실제 API에 해당 내용을 적용하려고 보니 Domain 단 건 조회보다는 List<Domain>을 반환하는 경우가 훨씬 많았습니다. 따라서 List<Domain>을 List<Response>로 변환해야 하는데 해당 작업을 for문이나 Stream으로 Controller로 처리하려니 Controller 코드도 지저분해지고 Controller가 하는 역할에 부합하지 않게 되는 것 같습니다.List<>를 변환할 때는 어디서 하는게 올바른 것인지 질문드립니다!
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
세션아이디에 대해 질문드립니다..
HttpSession session = request.getSession();을 하게되면 쿠키가 생성되고, 쿠키의 이름은 JSESSIONID, 쿠키의 값은 랜덤값이라고 이해했습니다. 하지만 이전 강의를 보면 쿠키의 값을 세션id와 동일하게 설정을하고, 쿠키의 값을 통해 세션저장소에서 세션을 조회했는데요. 하지만 코드에서는 session.setAttribute(SessionConst.LOGIN_MEMEMBER, loginMember)로 상수를 세션id(key)로 지정했는데 이렇게 하면 SessionConst.LOGIN_MEMEMBER를 통해 세션저장소에서 세션을 조회해야하지않나요? 쿠키의 value와 세션저장소의 세션id가 동일하지않은데 어떻게 조회할수 있는지 궁금합니다..
-
미해결자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
deleteUser 관련 질문
현재 코드에서는 name을 기준으로 delete를 하는데요, findByName(name)을 이용한 코드에서 DB 안에 같은 이름의 회원이 2명 이상인 경우엔 오류가 생깁니다. 그 이유가 find는 return 개수가 1건이기 때문에 rollback 된다고 생각했습니다.이 버그를 수정하기 위해서 deleteUser의 파라미터는 Long id 로 수정했는데, 또 안 되더라고요...?findAll을 쓰면 같은 이름을 가진 모든 회원이 삭제될 것 같고... 어떻게 하면 동명이인의 회원 중에서 내가 원하는 한 회원만 삭제할 수 있나요? + 추가 방금 다른 학생분의 질문과 답변을 읽었습니다. 같은 내용의 질문인 것 같네요!그러면 파라미터를 Long id 로 변경하되, 현재 실습 중인 UI에서도 코드를 수정해야하는 부분이 있기에 삭제가 안 되는 게 맞다고 이해하면 될까요?
-
미해결스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
v1~v5에서 어느정도까지 알고넘어가야하는지 질문드립니다
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)ㄴ[2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)네3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)네[질문 내용]v5까지 강의를 진행했는데요코드를 다 따라하긴했는데 v3부터 각 코드가 무슨 역할을 하는지 이건 왜 이렇게 되는지 확실하게 짚고 넘어가는게 힘드네요..ㅠㅠ v1~v5까지는 mvc의 변화과정이니까 세세하게 코드를 이해하려 하지 말고 그냥 여기서는 왜 이렇게 바꾸는지, 이전 버전과 다른건 뭔지 등 큰 틀만 알고 넘어가도 큰 문제 없을까요?
-
미해결스프링 핵심 원리 - 고급편
@target 관련
안녕하세요 강의 잘 듣고 있습니다.강의 말미에 args, @args, @target은 단독으로 사용하면 안 된다고 하셨고 다음과 같은 이유를 말씀하셨습니다. '실제 객체 인스턴스가 생성되고 런타임에 적용 여부를 알 수 있다'아규먼트의 실제 타입을 요구하는 args, @args는 비교적 직관적으로 이해했는데, @target은 어째서 런타임에 적용 여부를 알아야만 하는 걸까요? 마치 @within이 그런 것처럼 클래스 내부에 특정 어노테이션이 있으면 해당 클래스부터 부모 클래스까지 AOP를 적용하면 될 것 같은데 말이죠.
-
해결됨스프링 핵심 원리 - 고급편
포인트컷 표현식 질문
안녕하세요 강의 잘 듣고있습니다.강의에서 등장하는 AtTargetAtWithinAspect의 execution 표현식을 보면 * hello.aop..*(..)로 기재되어 있습니다.이전 강의에서 학습했던 표현식(* hello.aop..*.*(..))과 어떤 차이점이 있는건가요?
-
해결됨스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
MVC 패턴에서의 검증 책임이 누구에게 있는 지 궁금합니다
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]여기에 질문 내용을 남겨주세요.안녕하세요 MVC 패턴에 대해 생각해보다가 고민이 생겨 질문을 남겨봅니다! 강의를 보면 사용자의 입력값 내지 요청에 대한 입증 책임을 가지는 것은 Controller이고, 그 요청에 대한 비즈니스 로직에 관한 검증 책임은 Service쪽에서 가져간다고 보는 것이 맞을까요? 예를 들어 회원가입을 하는 상황이라고 할 때, "닉네임은 한글로만 이루어진다"라는 상황에서 닉네임을 영어로 쳤다고 가정하면 이에 대한 검증은 Controller, "회원 간 중복된 닉네임은 가질 수 없다"라는 상황에선 Service 쪽에서 한다고 보는 것이 맞을까요? 그렇다면... view에서 검증을 하면 안 되는 이유나 비효율적인 예를 하나 들어주실 수 있으실까요??
-
해결됨재고시스템으로 알아보는 동시성이슈 해결방법
트랜잭션 전파속성, 데이터 소스
안녕하세요. 강의 잘 보고 있습니다. 의문이 생겨 질문을 남깁니다. 트랜잭션 전파속성을 REQUIRES_NEW로 해서 새로 생성한 이유가 있을까요? 그냥 REQUIRED로 하면 안되나요??강의 내에서 데이터소스를 분리하는 것을 추천해주셨는데, 커넥션 풀 사이즈를 늘리면 안되나요?? 감사합니다.
-
미해결스프링 시큐리티 OAuth2
Naver Login시 권한에 대해 질문이 있습니다
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); } }
-
해결됨스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
ResponseStatusException
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]ResponseStatusException 예외에서 3번째 파라미터에 illeagalArgumentException 예외를 넣어주셧는데 그말은 IlleaglArgumentException 이 컨트롤러에서 터지면 500 에러인데 ResponseStatusException 에 담아줬기 떄문에 404 에러로 바뀌는건가요 ?
-
미해결실전! 스프링 부트와 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 lombok.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.util.List;import java.util.stream.Collectors;import static java.util.stream.Collectors.toList;@RestController@RequiredArgsConstructorpublic 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> orderItems = order.getOrderItems();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=" + order.getId());}List<OrderDto> collect = orders.stream().map(o -> new OrderDto(o)).collect(toList());return collect;}@Datastatic 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());}}@Datastatic 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 fetch o.delivery d" +" join fetch o.orderItems oi" +" join fetch oi.item i", Order.class).getResultList();}
-
미해결실전! 스프링 부트와 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 :selecto1_0.order_id,o1_0.deliver_id,o1_0.member_id,o1_0.order_date,o1_0.statusfromorders o1_0joinmember m1_0on m1_0.member_id=o1_0.member_idfetchfirst ? rows only2023-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/~/jpashop2select 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 onlyselect 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 :selectm1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.namefrommember m1_0wherem1_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/~/jpashop2select 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 :selectd1_0.delivery_id,d1_0.city,d1_0.street,d1_0.zipcode,d1_0.statusfromdelivery d1_0whered1_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/~/jpashop2select 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 :selecto1_0.order_id,o1_0.deliver_id,o1_0.member_id,o1_0.order_date,o1_0.statusfromorders o1_0whereo1_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/~/jpashop2select 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 :selectm1_0.member_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.namefrommember m1_0wherem1_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/~/jpashop2select 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 :selectd1_0.delivery_id,d1_0.city,d1_0.street,d1_0.zipcode,d1_0.statusfromdelivery d1_0whered1_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/~/jpashop2select 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 :selecto1_0.order_id,o1_0.deliver_id,o1_0.member_id,o1_0.order_date,o1_0.statusfromorders o1_0whereo1_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/~/jpashop2select 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 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;/*** X To One (컬렉션 X)* 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개List<Order> orders = orderRepository.findAllByString(new OrderSearch());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.findAllWithMemberDelivery();List<SimpleOrderDto> result = orders.stream().map(o -> new SimpleOrderDto(o)).collect(Collectors.toList());return result;}@Datastatic 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 fetch o.delivery d", Order.class).getResultList();}
-
미해결
스프링 사용 중 생기는 오류
안녕하세요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로 표시하였는데 혹시 다른 추가적이 방법이 있을까요
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
내용정리 화면은 어디서 볼수있나요?
화면에서 보여주시는 내용정리된 노트?는 어디서 볼수있나요?
-
해결됨스프링 핵심 원리 - 기본편
프레임워크 없이 순수한 자바 코드를 단위 테스트 하는 경우
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]학습 자료의 생성자 주입을 선택하라는 내용에서 '누락' 설명하는 부분에 써진 내용을 보고 질문 드립니다. 아래는 학습 자료에 있는 내용 복붙한 거입니다.프레임워크 없이 순수한 자바 코드를 단위 테스트 하는 경우에 다음과 같이 수정자 의존 관계인 경우 @Autowired가 프레임워크 안에서 동작할 때는 의존 관계가 없으면 오류가 발생하지만, 지금은 프레임워크 없이 순수한 자바 코드로만 단위 테스트를 수행하고 있다. 이렇게 테스트를 수행하면 실행은 된다. 그런데 막상 실행 결과는 NPE(Null Point Exception)이 발생하는데, memberRepository, discountPolicy 모두 의존 관계 주입이 누락되었기 때문이다 여기서 말하고자 하는 바는"프레임워크 없이 순수한 자바 코드를 단위 테스트 하는 경우엔 수정자 주입 방법의 경우 문제가 생긴다."가 아니라"수정자 주입을 하면 만일 개발자의 실수로 뭔가를 누락할 경우 발견하기 어려울 수 있다. 그러므로 수정자 주입을 안 하는 게 좋다."라는 게 맞나요? 즉 수정자 주입으로 해도 테스트할 수는 있지만 여러모로를 따졌을 때 생성자 주입이 실수할 확률이 적어서 낫기 때문인지 궁금합니다. 단위 테스트할 때 set 메서드를 직접 호출하면 수정자 주입의 경우에도 자바로 단위 테스트 할 수는 있는 거죠? 제가 코드를 짰을 땐 되는 것 같은데 제가 제대로 코드를 짠 게 아닐 수 있어서 검증이 제대로 된 건지 모르겠어서 질문드립니다.
-
해결됨스프링 핵심 원리 - 기본편
setter와 생성자 모두에 @Autowired를 하면 주입이 중복해서 되나요?
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]수정자 주입 설명하시는 강의 내용 중9:55 부분부터 setter에 있는 @Autowired 2개를 지우고 실행했더니 아무 것도 출력이 안 되었는데, 생성자 부분에서 soutv를 다시 추가하고 실행해 보니 생성자 주입은 정상적으로 되는 것 같더라고요. 그런데 setter에 @Autowired를 붙이고,soutv는 setter와 생성자 모두에 넣고 AutoAppConfigTest를 실행하면setter의 soutv와 생성자의 soutv 모두 실행되고 다음과 같이 출력됩니다.memberRepository = hello.core.member.MemoryMemberRepository@4e70a728discountPolicy = hello.core.discount.RateDiscountPolicy@b7838a9memberRepository = hello.core.member.MemoryMemberRepository@4e70a728discountPolicy = hello.core.discount.RateDiscountPolicy@b7838a9 그럼 setter 주입도 되고, 생성자 주입도 된 건가요? 불필요하게 또 주입을 하게 되었다는 뜻인가요? @Component public class OrderServiceImpl implements OrderService { private MemberRepository memberRepository; private DiscountPolicy discountPolicy; @Autowired public void setMemberRepository(MemberRepository memberRepository) { System.out.println("memberRepository = " + memberRepository); this.memberRepository = memberRepository; } @Autowired public void setDiscountPolicy(DiscountPolicy discountPolicy) { System.out.println("discountPolicy = " + discountPolicy); this.discountPolicy = discountPolicy; } @Autowired public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) { System.out.println("memberRepository = " + memberRepository); System.out.println("discountPolicy = " + discountPolicy); this.memberRepository = memberRepository; this.discountPolicy = discountPolicy; }