월 17,600원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
n+1
안녕하세요 영한님 20:07 부분에서 n+1 현상이 나타나신다고 말씀을 주셨는데 이 부분은 루프를 돌면서 컬렉션을 직접 추가한 부분이라 어쩔수 없는 상황아닌가요?? 결과론적으론 N+1 현상이 나타났다고 이해 하면 될까요?
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
강의 수강 후 개인공부 진행하면서 궁금한 점 질문드립니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(http://bit.ly/3fX6ygx)을 먼저 확인해주세요. 3. 질문 잘하기 메뉴얼(http://bit.ly/2UfeqCG)을 먼저 읽어주세요. 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 안녕하세요 영한님, JPA 강의를 모두 수강 후 개인적으로 토이 프로젝트를 진행해보면서 궁금한 점이 있어서 질문드립니다. 가정) Entity에서 값타입인 필드가 존재하는데, 값타입이 List나 Set 형식으로 존재합니다. 아래와 예시와 같이 Store(Entity)는 여러 Category(Value)를 가질 수 있도록 구성했습니다. 위 예시에서 특정 카테고리에 해당하는 Store Entity를 조회하고 싶은데 JPA로는 구현이 힘들어 보입니다. 또한, QueryDSL을 쓰려고 했는데 Category가 Entity 타입이 아니다 보니 Category 테이블과 Join을 할 수 없더라구요. 제가 생각한 방식은 Store를 findByAll을 해서 Category를 찾는거였는데 이렇게 할 경우 리소스 낭비가 심하다고 생각됩니다. 또 다른 방식은 Category를 하나의 Entity로 보고 Store-Category를 1:N 관계로 가져가는 방법을 생각해봤는데, Category가 지속적으로 수정이 필요하지도 않고 별도의 Entity로 가져가기엔 DDD 방법론에 맞지 않는다는 생각이 듭니다. 이런 경우에는 어떤 방식으로 구현을 해야 할까요? 조언 부탁드립니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
궁금한게 있습니다
강의해서 1:N 은 페이징처리를 하려고하면 인메모리로 다 올려버린다고 이해하였습니다. 하지만 약간 이해가 안된다고 해야될까요? 결론적으로 정확하게 메커니즘을 제가 이해를 못하는거 같습니다. 강의를 3~4번 다시 보구 있습니다만 몇가지 질문드립니다. 1. jpql에서 1:N으로 fetch join을 하여 뻥튀기? 데이터가 되어 distinct로 해결하였습니다. 여기서 추가로 페이징을 넣으면 인메모리로 바꿘다고하셨는데, 정확하게 jpa에서 예를 들면 select distinct o from order o join fetch o,orderItems oi 이렇게 하구 페이징처리를 하면 인메모리로 된다고하셨는데 distinct를 하기전에 jpql이 1:N인걸 인지하고 인메모리로 일다누올린다는건지 궁금합니다 2. 위에 내용과 동일하게 단순히 1:N 어노테이션만 보구 컬렉션 연관관계가 되는기준으로 페이징을 처리하면 워닝 에러가 나는지 궁금합니다
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
update 뒤에 findOne 하면 문제가 생길 거 같습니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(http://bit.ly/3fX6ygx)을 먼저 확인해주세요. 3. 질문 잘하기 메뉴얼(http://bit.ly/2UfeqCG)을 먼저 읽어주세요. 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예[질문 내용] 여기에 질문 내용을 남겨주세요. 회원 수정 api 강의에서 update 매서드가 id 만 반환하게 하고 바로 뒤에 findOne으로 다시 Member 조회를 하는데요. 보통 저런 경우 트랜잭션을 나눠서 update 는 마스터 디비에서 실행하고 findOne은 슬레이브 디비에서 실행하게 될 텐데 저렇게 바로 이어서 써버리면 master 에서 slave 로 동기화되기 전에 slave에 리드 쿼리가 날라가서 업데이트 이전 데이터가 나올 수 있을 것 같은데, 이러면 문제가 되지 않을까요? 그래서 그냥 update 에서 반환할 때 entity 객체 그대로 반환하는 게 좋을 것 같아서 질문드립니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
JPQLQuery 사용시 order by 질문 드립니다
질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 안녕하세요~ JPQLQuery 사용시 order by 를 할 때 대상컬럼이 숫자가 아니라 문자형인 경우에 대한 질문입니다. 예를 들어 데이터가 10, 20, 100 이면 숫자일 때는 크기순으로 정렬에 문제가 없는데 문자형일 때는 결과가 다르네요(당연하지만 ㅎ) .orderBy 내에서 대상 컬럼을 int 형으로 캐스팅해서 쓰는 것도 안되고.. 좋은 방법이 없을지 고견을 여쭙습니다. 감사합니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
파티션 테이블 사용에 관련해서 질문드립니다.
안녕하세요. 다름 아니라, JPA, querydsl로 시스템 운영 중, 고객의 요구사항으로 partition 테이블을 적용해야 하는 일이 생겼는데, 파티션 테이블을 사용하기 위해서는 select * from user PARTITION (2021) 과 같이 파티션 이름을 같이 써줘야 속도가 나온다고 하는데 JPA에서도 partition 키워드를 사용할 수 있나요? 쓸 수 없다면 성능에 크게 문제가 없을까요? db tool에서는 partition 키워드를 넣지 않으면 where절에 range로 잡은 컬럼을 검색조건에 넣어도 '작업계획 보기' 에서 PARTITION RANGE(ALL)로 표시가 됩니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
totalPrice
안녕하세요 15:48 보시면 totalPrice 값이 나오는데 이 메소드는 언제 호출이 된건가요? 따로 호출해 준적이없는거 같습니다 ========== @GetMapping("/api/v1/simple-orders")public List<Order> ordersV1(){ List<Order> all = orderRepository.findAllByString(new OrderSearch()); return all;} =========== public int getTotalPrice(){ int totalPrice = 0 ; for(OrderItem orderItem : orderItems){ totalPrice+=orderItem.getTotalPrice(); } return totalPrice;}
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
일대다 페치조인 메모리상에서 페이징
안녕하세요 영한님 강의 잘 듣고 있습니다!! 일대다 페치조인에서 페이징을 하게되면, 메모리 상에서 페이징을 한다고 이해했습니다. 만약 페치조인 쿼리가 DB로 가면, 뻥튀기된 로우들이 메모리에 올라오게 되고 distinct를 JPA가 하게됩니다. 이 상황에서 만약 페이징이 이루어진다면 뻥튀기된 로우에서 offset만큼 결과를 리턴하게 되다고 이해했습니다. 결론적으로 생각하면 뻥튀기된 로우를 페이징하기 위한 쿼리와 전체를 가져오는 쿼리가 같은 상황에서, 왜 메모리상에서 페이징하는 것이 위험한가요?
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
영속성 컨텍스트에 먼저 있을 것 같습니다 !
안녕하세요! 6분 31초 부분 질문드립니다.(update 메서드) memberRepository.findOne(id)에서 membrer 객체를 찾아올 때, 영속성 컨텍스트에 없을 거니까 DB에서 조회할거라고 말씀하셨는데요, 사용자 -> name이 jjj으로 가입 , 자동으로 id 13번 등록 ->영속성 컨텍스트에 남음 -> 사용자 -> id가 13인 것을 name nnn으로 변경 -> memberRepository.findOne(13) -> 영속성 컨텍스트에서 변경감지 -> 영속성 컨텍스트 값 초기화(name:nnn)->DB에 값 변경(jjj -> nnn) 이렇게 이해를 했는데 혹시 제가 잘못 생각한 부분이 있을까요??ㅠㅠ
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
필요한 값만 외부에 반환할 때의 방법
안녕하세요, 특정 값들을 조회하는 api를 설계할 때에, 엔티티 자체를 반환해서도 안되며 필요한값들을 dto로 만들어서 반환하는 방법이 있다는 것도 이해했습니다. 그럼 실무에서는 모든 상황에 맞추어서 그에 해당하는 값들만 반환해주는 api들이 각각 존재하는지 궁금합니다. 예를들어 1번화면에서는 회원명,상품명,상품이미지,상품가격 이 필요하고 2번 화면에서는 회원명,상품명,상품이미지,상품가격,카테고리,평점 이 필요한 등 여러군데에서 조금씩의 차이만 존재하는 경우가 있을 것 같은데(스스로 토이 프로젝트를 진행하다보니 이런 경우가 많더라구요..) 이런경우 주로 어떤 방식을 사용하는지 궁금합니다. 각 상황에 fit하게 맞는 dto를 내주는 api들이 존재하는지, 포괄된 항목들을 뿌려주면 view 단(앱이나 웹)에서 알아서 필요한 값들만 뽑아서 사용하는지 궁금합니다. 쉬지않고 좋은 강의 올려주셔서 감사합니다. 강사님 보면서 자극도 많이 받는 것 같습니다. 앞으로도 잘 복습하고 따라가겠습니다!
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
spring boot
코드는 동일한데... 스프링 부트 버전떄문인진몰라도 맴버 딜리버리 엔티티에 지연로딩을 해서 그쪽에 값이 없다고 에러가 뜨는거 같습니다 ㅠㅠ 아무래도 최신버전이라 그런걸까요.. ㅠㅠ { "timestamp": "2021-08-17T03:18:17.589+00:00", "status": 500, "error": "Internal Server Error", "trace": "org.hibernate.LazyInitializationException: could not initialize proxy [jpabook.jpashop.domain.Member#1] - no Session\n\tat org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:170)\n\tat org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:310)\n\tat org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:45)\n\tat org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95)\n\tat jpabook.jpashop.domain.Member$HibernateProxy$nCeQGWjH.getName(Unknown Source)\n\tat jpabook.jpashop.api.OrderSimpleApiController$SimpleOrderDto.<init>(OrderSimpleApiController.java:59)\n\tat jpabook.jpashop.api.OrderSimpleApiController.lambda$orderV2$0(OrderSimpleApiController.java:43)\n\tat java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)\n\tat java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1384)\n\tat java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)\n\tat java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)\n\tat java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)\n\tat java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)\n\tat java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)\n\tat jpabook.jpashop.api.OrderSimpleApiController.orderV2(OrderSimpleApiController.java:44)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n\tat java.lang.reflect.Method.invoke(Method.java:498)\n\tat org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)\n\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)\n\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)\n\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)\n\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\n\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1063)\n\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)\n\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)\n\tat org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:655)\n\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:764)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:228)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)\n\tat org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1723)\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n\tat java.lang.Thread.run(Thread.java:748)\n", "message": "could not initialize proxy [jpabook.jpashop.domain.Member#1] - no Session", "path": "/api/v2/simple-orders" 코드를 보시면 아래에 order.getMember().getName(); 이렇게 호출했을때 해당 member값이 호출이 안되서 에러가 납니다... 전 시간에 EAGER로 바꾸면 안된다고 하셔서 혹시 몰라서 지연로딩으로 바꾸니까 동작이 잘되서... v2에서 지연로딩으로하고 getmember().getName() 부르면 위와 같은 에러가 나는거 같습니당.. @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 개발과 성능 최적화
Could not write JSON: failed to lazily initialize a collection of role
안녕하세요. 질문드립니다. 원인과 해결방법은 알지만 왜 그럴까라는건 짐작이 안가서 질문드립니다. 일단 에러 내용입니다.. { "timestamp": "2021-08-16T04:43:26.660+00:00", "status": 500, "error": "Internal Server Error", "trace": "org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: failed to lazily initialize a collection of role: jpabook.jpashop.domain.Member.orders, could not initialize proxy - no Session; nested exception is com.fasterxml.ja 뒤에 내용이 더 있지만 쓸모없는 내요인거 같아서 뺐습니다. 막상 검색해보니 이런 에러이고, 이분은 https://ankonichijyou.tistory.com/entry/JPA-OneToMany-%EC%98%A4%EB%A5%98 FetchType.EAGER 이렇게 적용해서 해당 에러를 푸셨다고 하셨습니다. 결론적으론 order라는 값이 빈값이라 에러가 났던 원인이었고, 강의해서 사용하신 @JsonIgnore 라는 값을 이용해서 Member 엔티티 Order 쪽에 넣으면 에러가 사라지긴합니다만 oneToMany 디폴트가 지연로딩인데.. 즉시로딩으로 바꾸니까 에러가 사라지는데.. 강의에선 무조건 지연로딩으로 잡고 시작하라고 하셔서 어떤걸 선택할지 애매합니다.. 1. 즉시로딩을 선택해야되는지..? 2. 이그놀로 처리..? 근데 추후 유지보수가 힘들꺼같다 3. dto로 처리
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
JPA 책의 LAZY + JPQL 질문입니다.
좋은 강의 감사합니다.연관관계 fetch Type을 LAZY로 설정하고, JPQL을 이용해 하나의 엔티티만 조회하도록 하면, 실제로 연관 대상 엔티티를 사용하기 전까지는, query가 발생하지 않는 것으로 이해를 했는데, 다음과 같은 현상이 발생하는데 잘 이해가 가질 않습니다 도와주세요.. ㅠ
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
스트림관련식
ordersV6의 스트림식에서 orderQuerydto를 키로 하고 orderitemquerydto의 list를 밸류로 한것 같은데 multivaluemap이 아닌 그냥 map은 키가 같을때 밸류를 덥어씌우는것으로 알고 있는데 어떻게 밸류가 list<orderquerydto>형태로 저장될수 있는지 궁금합니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
MemberApiController에 static으로 만들어져 있는 Result<T> 메소드를 OrderApiController에서 써도 상관없나요?
@GetMapping("/api/v2/orders")public MemberApiController.Result orderV2() { List<Order> orders = orderRepository.findAllByString(new OrderSearch()); List<OrderDto> collect = orders.stream() .map(o -> new OrderDto(o)).collect(Collectors.toList()); return new MemberApiController.Result(collect);} 이렇게 만들어지는데, 아무런 상관이없는지 궁금합니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
pagination query dsl
안녕하세요 강사님, 페이지네이션 query dsl로 페치조인 적용시에 아래와 같은 pageable 쿼리는 사용이 힘든건가요!?``` public PageImpl<StoreVo> findStoresByNamePaging(String name, Pageable pageable) { JPQLQuery<StoreVo> query = jpaQueryFactory // 1) .select(Projections.fields(StoreVo.class, store.id , store.name , store.address )) .from(store) .where(store.name.eq(name)); long totalCount = query.fetchCount(); // 2) List<StoreVo> results = getQuerydsl().applyPagination(pageable, query).fetch(); // 3) return new PageImpl<>(results, pageable, totalCount); // 4) } ```
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
연관관계 편의 메서드/추가쿼리 관련 질문이 있습니다.
삭제된 글입니다
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
post를 통해서 넘어오는 데이터 처리 관련 부분 질문 드립니다
안녕하세요 강의 잘 듣고 있습니다 post를 통해서 json 객체가 넘어져 올때 만약 memeber 관련 데이터가 넘어올경우 @RequestBody를 사용해서 Member 클래스 매개변수에 주입이 되는 것으로 알고 있습니다. 이때 @PutMapping("/api/v2/members/{id}")public UpdateMemberResponse updateMemberResponse(@PathVariable("id") Long id, @RequestBody @Valid UpdateMemberRequest request){ memberService.update(id, request.getName()); Member member = memberService.findOne(id); return new UpdateMemberResponse(id, member.getName());} 부분에서 request 객체가 @Datastatic private class UpdateMemberRequest { private String name;} 에서 어떤 생성자를 통해서 주입이 되는지 잘 모르겠습니다. 해당 updateMemberRequest클래스에는 기본 생성자 와 @Data에 있는 RequiredArgsConstructor 정도만 있는 것으로 알고 있는데 name에 어느 방식으로 주입이 되는지 궁금합니다 추가로 RequiredArgsConstructor는 NotNull이나 final 로만 지정된 변수들에 대해서만 초기화가 진행되는 것으로 알고있는데 이게 notnull이 아니라 notnull에도 적용 되는지 궁금합니다 감사합니다.
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
@Transactional(readOnly = true)에 대해 궁금한 점 있습니다!
안녕하세요. 강의를 듣던 중 궁금한 것이 생겨서 질문 드립니다! @Service@Transactional(readOnly = true) 이 옵션을 Service 계층에만 붙이던데 사실 진짜 DB에 쿼리를 날리는 계층은 repository 계층인데 왜 Service 계층에 붙이는지 궁금합니다!
- 미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
회원 수정 API에서 질문 있습니다!
memberService에서 어떤 메서드는 @Transactional 어노테이션을 붙이고 어떤 메서드는 안붙이던데 기준이 무엇인지 궁금합니다! @Transactional //데이터를 변경하는 메서드에서 readOnly = true 옵션을 붙이면 변경이 되지 않는다!public Long join(Member member) { validateDuplicateMember(member); //중복 회원 검증 memberRepository.save(member); return member.getId();}private void validateDuplicateMember(Member member) { List<Member> findMembers = memberRepository.findByName(member.getName()); if (!findMembers.isEmpty()) { throw new IllegalStateException("이미 존재하는 회원입니다."); }}/**전체 회원 조회 **/public List<Member> findMembers() { return memberRepository.findAll();}public Member findOne(Long memberId) { return memberRepository.findOne(memberId);}@Transactionalpublic void update(Long id, String name) { Member member = memberRepository.findOne(id); member.setName(name);} 또한 MemberApiController에서 어떤 메서드는 static을 붙이고 어떤 메서드를 안붙였던데 기준이 궁금합니다! 마지막으로 이건 기초 자바 문법인거 같은데 왜 외부에서 MemberApiController 객체를 생성한 뒤 memberApiController.createMemberResponse or .CreateMemberRequest 와 같이 @Data가 붙은 메서드는 접근이 불가능한지 궁금합니다! @Datastatic class CreateMemberRequest { private String name;}@Dataclass CreateMemberResponse { private Long id; public CreateMemberResponse(Long id) { this.id = id; }}