묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
내부 클래스에 대해서 질문있습니다
안녕하세요 강의듣다가 궁금한 점이 생겼습니다 @Component("helloBean") static class HelloBean { .... } 이 부분인데요 BasicController는 스프링이 자동으로 컴포넌트 스캔을 해주면서 빈등록이 되는데 컨트롤러가 빈등록이 되면서 @Component 애노테이션을 써준 내부 클래스도 자동으로 빈등록이 되지않나요? 그러면 당연히 타임리프에서 사용할 수 있는데 왜 강의에서 static 키워드를 넣어준건지 궁금합니다.
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
OrderITemDto 클래스 생성 위치
안녕하세요 좋은 영상 감사합니다. 다름이 아니라 OrderItemDto 는 OrderDto 안에서 사용하는 클래스이므로 OrderItemDto(내부 클래스) 의 다시 내부 클래스로 생성하는 것이 맞지 않나요? 영상에서는 OrderDto 와 동등한 레벨로 생성하셔서 궁금증이 들었습니다. 감사합니다^^
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
SpringBoot 버전 변경 후 매핑 문제
안녕하세요 강의를 보여 따라하던중 @NotEmpty 어노테이션이 안되는걸보고 질문을 검색하니 SpringBoot 버전을 변경해야 한다고 하셔서 build.gradle 파일을 교재에 나와있는데로 복붙하였습니다. 근데 그 이후부터 localhost:8080을 들어갈때 마다 아래와 같은 에러가 나면서 들어가지지를 않습니다. 코드에 문제가 있는건지 궁금합니다. 그리고 main밑에 생긴 generated 폴더도 무엇인지 궁금합니다. 2022-02-02 11:43:18.412 ERROR 12428 --- [nio-8080-exec-3] org.thymeleaf.TemplateEngine : [THYMELEAF][http-nio-8080-exec-3] Exception processing template "home": Error resolving fragment: "~{'fragments/footer' :: footer}": template or fragment could not be resolved (template: "home" - line 28, col 10) org.thymeleaf.exceptions.TemplateInputException: Error resolving fragment: "~{'fragments/footer' :: footer}": template or fragment could not be resolved (template: "home" - line 28, col 10) at org.thymeleaf.standard.expression.FragmentExpression.resolveExecutedFragmentExpression(FragmentExpression.java:619) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.standard.processor.AbstractStandardFragmentInsertionTagProcessor.computeFragment(AbstractStandardFragmentInsertionTagProcessor.java:379) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.standard.processor.AbstractStandardFragmentInsertionTagProcessor.doProcess(AbstractStandardFragmentInsertionTagProcessor.java:110) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.engine.ProcessorTemplateHandler.handleStandaloneElement(ProcessorTemplateHandler.java:918) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.engine.StandaloneElementTag.beHandled(StandaloneElementTag.java:228) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.engine.TemplateModel.process(TemplateModel.java:136) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:592) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:362) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:189) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1394) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1139) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1078) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.2.jar:5.3.2] at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.41.jar:4.0.FR] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.2.jar:5.3.2] at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.41.jar:9.0.41] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.2.jar:5.3.2] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.2.jar:5.3.2] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.2.jar:5.3.2] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.2.jar:5.3.2] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.2.jar:5.3.2] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.2.jar:5.3.2] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na] 2022-02-02 11:43:18.413 ERROR 12428 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: Error resolving fragment: "~{'fragments/footer' :: footer}": template or fragment could not be resolved (template: "home" - line 28, col 10)] with root cause org.thymeleaf.exceptions.TemplateInputException: Error resolving fragment: "~{'fragments/footer' :: footer}": template or fragment could not be resolved (template: "home" - line 28, col 10) at org.thymeleaf.standard.expression.FragmentExpression.resolveExecutedFragmentExpression(FragmentExpression.java:619) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.standard.processor.AbstractStandardFragmentInsertionTagProcessor.computeFragment(AbstractStandardFragmentInsertionTagProcessor.java:379) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.standard.processor.AbstractStandardFragmentInsertionTagProcessor.doProcess(AbstractStandardFragmentInsertionTagProcessor.java:110) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.engine.ProcessorTemplateHandler.handleStandaloneElement(ProcessorTemplateHandler.java:918) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.engine.StandaloneElementTag.beHandled(StandaloneElementTag.java:228) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.engine.TemplateModel.process(TemplateModel.java:136) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:592) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:362) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:189) ~[thymeleaf-spring5-3.0.11.RELEASE.jar:3.0.11.RELEASE] at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1394) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1139) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1078) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.2.jar:5.3.2] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.2.jar:5.3.2] at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.41.jar:4.0.FR] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.2.jar:5.3.2] at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.41.jar:9.0.41] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.2.jar:5.3.2] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.2.jar:5.3.2] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.2.jar:5.3.2] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.2.jar:5.3.2] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.2.jar:5.3.2] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.2.jar:5.3.2] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.41.jar:9.0.41] at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
update 메소드가 void 인것과 관련된 질문 드립니다.
안녕하세요. update 메소드는 커맨드 쿼리 분리 원칙에 따라서 member 객체를 반환하지 말고 void로 반환값이 없게 하거나 id정도만 반환하라고 하셨습니다. 1. 커맨드가 수정이니 쿼리로 member를 찾지 말아야 한다고 하셨는데 findOne 메소드에서 어차피 member를 찾아야 하는 것 아닌가요? 2. update 메소드 외에도 사실 모든 메소드에서 void나 id만 반환해야 하는 것인가요? 다른 메소드도 등록, 수정, 삭제 등등 멤버를 조회하는 것이 커맨드가 아닌 것 같은데, 그렇다면 일반적으로 반환을 id만 해주는 것이 좋은가요? 감사합니다.
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
안녕하세요 영한님 강의를 벗어난 주제 이긴한대 궁금한게 생겨서 질문드립니다.
유저와 팔로우 팔로잉 Entity 를 구현하려고 하는데 이렇게 하는게 맞는건지 잘 모르겠어서 질문드립니다.. 조금이라도 힌트를 주신다면 정말 감사할것 같네요!!
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
BatchSize, Batch Fetch Size 옵션이 적용되지 않는 문제
안녕하세요 영한님 강의 잘 듣고 있습니다! 해당 강의에서 글로벌전략을 지연로딩 설정후 Order -(one to Many) - OrderItemList -(Many To One)- Item 연관관계의 엔티티에 BatchSize, Batch Fetch Size 옵션을 적용해 3계층 깊이를 가진 엔티티 그래프를 조회하면 총 쿼리가 계층별로 하나씩, 3개 날라간다고 이해를 했습니다. 그런데 jdk 11, 스프링 Data Jpa와 mysql 등 약간의 환경 변화후 같은 예제로 테스트해보니 1. order 쿼리 2. orderItemList의 N개 쿼리(강의에서는 총 2개) 3. 이후 in절로 묶인 item 쿼리가 위의 N개쿼리때문에 N개 총 5개의 쿼리가 날라가는 현상이 발생했습니다. 요약하면 첫 연관 엔티티 orderitem은 batchsize 옵션이 적용되지 않아 N개의 쿼리가 날라가고 이후에 배치 옵션이 적용되어 각각 in절로 묶인 item 엔티티 쿼리가 날라가고있습니다. 이것저것 조작하다가 서비스단에서 transaction 어노테이션을 제거하니 강의에서처럼 엔티티 그래프 계층별로 한개씩 쿼리가 3개로 바뀌어 날라가는데 이유를 잘 모르겠습니다. transaction(Readonly = true) 일때도 정상적으로 쿼리가 3개 날라가는거보면 transaction(Readonly = false) 상황에서만 발생하는 문제같은데 혹시 원인을 알수 있을까요? 해당 문제를 고민하는 과정을 블로그에 글로 작성했는데 참조해서 정확한 원인을 알려주시면 정말 감사하겠습니다. https://www.jiniaslog.co.kr/article/view?articleId=559 언제나 양질의 강의 제공해주셔서 정말 감사하고 새해복 많이 받으세요!
-
미해결스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
핸들러 정보 채우는 방식?
안녕하세요, 이전에 V3, V4 등에서 핸들러 정보를 Map에 직접 저장했었습니다. 그러면 스프링 MVC 구조에서 핸들러 정보가 어떻게 채워지게 되나요?? 감사합니다. --- 질문이 애매한 것 같아서 추가합니다. ( ~ 4:49) /springmvc/v1/members/new-form HTTP 요청을 받은 후 어떻게 SpringMemberFormControllerV1 핸들러(컨트롤러)를 찾아올 수 있는지 정확하게 모르겠습니다. 그냥 클래스 레벨에 @Controller가 붙어있는 모든 클래스를 찾아서 그 안에 @RequestMapping으로 요청 받은 url과 동일한게 있다면 그 때 SpringMemberFormControllerV1 컨트롤러를 getHandelr()에서 반환하는 것인가요? 갑자기 애노테이션 기반 컨트롤러를 사용해서 이전 내용과 이어지질 않는 기분입니다.ㅠㅠ
-
미해결스프링 핵심 원리 - 고급편
@Aspect 안에 여러 어드바이스 작성 시, 어드바이저는 어떻게 구성이 되나요?
안녕하세요! 항상 좋은 강의 및 답변주셔서 감사합니다. 강의를 듣고 복습하던 도중 한 가지 궁금한 부분이 있어 글을 작성하게 되었습니다. @Aspect@Slf4jpublic class AspectV2 { @Pointcut("execution(* hello.aop..*.*(..))") public void allOrder(){} // public java.lang.String hello.aop.order.OrderRepository.save(java.lang.String) @Around("allOrder()") public Object doLog1(ProceedingJoinPoint joinPoint) throws Throwable { log.info("[log] {}", joinPoint.getSignature()); return joinPoint.proceed(); } @Around("allOrder()") public Object doLog2(ProceedingJoinPoint joinPoint) throws Throwable { log.info("[log] {}", joinPoint.getSignature()); return joinPoint.proceed(); }} 위의 코드에서 어드바이저는 총 몇개가 생기는지 궁금합니다. @Aspect가 있는 빈이 생길 경우, AutoProxyCreator가 @Aspect를 읽고 어드바이저를 작성해서 @Aspect Advisor 빌더 내부에 저장해두는 것으로 알려주셨는데요... 위의 코드가 실행되면, 어드바이저는 2개가 되는 걸까요? 아니면 1개만 되는 걸까요? 제가 이해하기로는 어드바이저는 주로 Default Advisor를 사용해서 1포인트컷 + 1어드바이저로 구성된다고 이해를 해서 2개가 생길 것으로 생각되긴 한데... 항상 좋은 강의 및 답변 해주셔서 고맙습니다. 감사합니다!
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
주문 목록 뷰에서 사용한 코드 관련 질문입니다.
강의를 다시 복습하면서 코드를 다시 유심히 보다가 발견하지 못한 부분을 발견해서 질문드립니다 주문 목록을 타임리프를 이용해서 뿌리는 코드는 다음과 같은데요 <tr th:each="item : ${orders}"> <td th:text="${item.id}"></td> <td th:text="${item.member.name}"></td> <td th:text="${item.orderItems[0].item.name}"></td> <td th:text="${item.orderItems[0].orderPrice}"></td> <td th:text="${item.orderItems[0].count}"></td> <td th:text="${item.status}"></td> <td th:text="${item.orderDate}"></td> <td> <a th:if="${item.status.name() == 'ORDER'}" href="#" th:href="'javascript:cancel('+${item.id}+')'" class="btn btn-danger">CANCEL</a> </td> </tr> 여기서 의문점이 Order와 Member는 다대일 관계이기 때문에 Order 리스트에 대해서 Order id와 Member 정보는 저렇게 출력하는게 가능한데 Order와 OrderItem은 1대다 관계인데 orderItems[0] 형태로 0 인덱스만 주었는데 출력이 되어있는데요 orderItems는 리스트인데 인덱스는 0만 주어서 출력하는 부분에서 타임리프 가이드를 보긴 했는데 이런 케이스에 대해서는 왜 이런식으로 코드가 나오는지 이해 안돼서 질문드립니다. 왜냐하면 저렇게 하면 하나의 Order에 대해서 Orderitem이 하나 밖에 나오지 않아서요 검증쿼리는 다음과 같이 던져서 검증 했구요 SELECT M.NAME, O.ORDER_ID, I.ORDER_PRICE, I.COUNT, IT.NAME FROM ORDERS O , ORDER_ITEM I , MEMBER M , ITEM IT WHERE 1=1 AND O.ORDER_ID = I.ORDER_ID AND M.MEMBER_ID = O.MEMBER_ID AND IT.ITEM_ID = I.ITEM_ID ORDER BY M.NAME ASC, O.ORDER_ID ASC, IT.NAME ASC, I.COUNT ASC 출력결과는 다음과 같습니다. 저런 상황이 발생하지 않도록 알맞게 처리하기 위해서는 view에 뿌려줄 수 있도록 적절한 DTO로 변환해서 뿌려줘야하는 것이 맞는지 궁금합니다.
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
파일 업로드와 관련되어 궁금한 부분이 있습니다 .
안녕하세요 영한님! 항상 강의를 열심히 시청하고 있는 취준생입니다! 상품 테이블이 있고 상품 이미지(상품이미지 파일의 경로) 테이블이 존재할 때 상품 수정 시 파일을 어떻게 수정하도록 작성해야 하는지 궁금한 점이 생겼습니다. 기존에 1 2 3 4 라는 파일의 이름으로 이미지가 저장되어 있고 수정 시 3 4 5 6 의 파일이 새로 요청될 때 3 4 번을 제외하고 1,2는 삭제 / 5 6 은 새로 갱신해주는 로직을 작성하는게 맞는 방법일지, 1 2 3 4를 한번에 다 삭제 후 새롭게 3 4 5 6 파일을 업로드 해주는게 깔끔한 방법일지 궁금증이 생겼습니다. 어떤게 더 좋은 방법일까요? 혹시 둘다 잘못된 방법이라면 어떻게 처리하는게 좋은 방법일까요?
-
미해결실전! 스프링 데이터 JPA
count query
안녕하세요 개발자님 스프링 커리큘럼 수강중인 학생입니다. 다름이 아니라 수업중 헷갈리는 부분이 있어 질문드립니다. 제가 알기로는 일대다 관계에서 left join을 하면 데이터가 뻥튀기(?) 된다고 알고 있는데 이때 join을 안하고 count쿼리를 따로 날리면 의도한 갯수가 안나올것 같다는 생각이 들었습니다. 그럼 team을 기준으로 left join을 할때는 count query를 따로 사용하면 안되는게 맞나요?? 제가 잘 이해한건지 궁금합니다. 글 읽어주셔 감사합니다. 좋은하루 되십시오
-
미해결스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
@PathVariable 사용 질문
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/)[질문 내용]안녕하세요! PathVariable을 사용하다 궁금한 점이 생겨 질문 남깁니다. 변수명과 원하는 name 설정이 같으면 생략할 수 있다고 하셨는데 이를 테스트 코드로 작성 시 오류가 발생합니다. (포스트맨으로 실행 시 성공..) Controller @ResponseBody @GetMapping("/test/{id}") public void test(@PathVariable Long id) { ... } Test Code @Test public void 테스트_코드() throws Exception { Long id = 1L; mvc.perform(get("/test/" + id)) .andExpect(status().isOk()); } Error org.springframework.web.util.NestedServletException: Request processing failed; java.lang.IllegalArgumentException: Name for argument type [java.lang.Long] not available, and parameter name information not found in class file either. 제가 조사한 바로는 아래와 같은데 (Spring 공식 문서 일부) The matching of method parameter names to URI Template variable names can only be done if your code is compiled with debugging enabled. If you do have not debugging enabled, you must specify the name of the URI Template variable name to bind to in the @PathVariable annotation. debugging enabled한 compile이라는걸 이해할 수 없어 질문 납겨봅니다ㅠ.ㅠ 답변 남겨주시면 감사합니다.
-
해결됨스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
@ResponseBody인 경우의 실행흐름이 궁금합니다.
안녕하세요. 항상 좋은 강의 감사합니다. 다름이 아니라 제가 정확히 이해가 안 가는 부분이 있어서 질문드립니다. @responseBody 애노테이션이 붙은 컨트롤러의 메서드는 다음과 같이 실행된다고 이해했습니다. Controller가 Http 메시지 바디에 쓸 내용 return -> ReturnValueHandler 의 구현체 중 RequestResponseBodyMethodProcessor 호출되어 HttpMessageConverter을 이용함. 위 과정과 관련해 강사님께서 @ResponseBody와 같이 view rendering이 필요 없는 작업들은 view가 생성되는 뒷 단의 작업들은(ViewResolver 와 View) 이루어지지 않는다고 설명해 주셨습니다. 그런데 여기서 의문점이 스프링 mvc의 DispatcherServlet 코드를 보면 mv = ha.handler(processedRequest, response, mappedHandler.getHandler()); 부분이 있습니다. 즉 어댑터를 통해 핸들러를 호출하면 항상 반환값으로 ModelAndView를 받습니다. 그럼 여기서 제가 궁금한 점이 생겼습니다. 클라이언트의 요청이 컨트롤러에서 @ResponseBody가 적힌 메서드가 호출되는 요청이라면 HttpMessageConverter에서 메시지 변환 과정을 진행 한 후 실제 Http 응답 메시지가 만들어서 클라이언트한테 전송되는 건가요?(이 경우는 실행흐름이 DispatcherServlet으로 가지 않고 종료) 아니면 HttpMessageConverter가 response 객체에 해당 값을 넣어두고, 흐름이 다시 DispatcherServlet으로 가서(그럼 여거서 mv는 null이 들어가나요?) 내부 로직에 의해 view를 만드는 과정이 생략되고 http 응답 메시지가 만들어지는 건가요?
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
V4 질문있습니다!
안녕하세요 영한님 서포터즈님들 V4에서 OrderQueryRepository 에 있는 findOrders 메서드에 대한 질문입니다. lazy인데 어떻게 member와 delivery가 같이 조회되는지 이해가 되질 않습니다.. m.name을 알기위해 member 엔티티를 select 해야한다고 생각을 했습니다 혹시 어느 부분이랑 제가 헷갈리는걸까요? 해당 단원 qna에서 해당 질문과 비슷한 게 있었는데 fetch join에 대해서만 말씀해주셔서 궁금해서 여쭤보게됐습니다 감사합니다 안녕하세요!! 질문 드리고 답을 기다리는 동안에 계속 찾아보고 생각해봤는데아직 저 자신한테 납득이 안되서요,, 혹시 맞는지 여쭤보고 싶습니다 API 개발 고급 - 지연 로딩과 조회 성능 최적화 강의에서 V4를 보고왔습니다 제가 의심한 부분은 "일반적인 SQL을 사용할 대 처럼 원하는 값을 선택해서 조회"입니다. 첫 번째 쿼리에 대한 데이터는 이렇게 되어있습니다 지연로딩은 프록시 객체를 만들어서 해당 엔티티의 필드를 사용할 때 DB에서 엔티티를 조회하는 것인데, 바로 DTO를 조회하는 것은 JOIN된 DB 값에서 member의 이름, delivery address 을 바로 뽑아서 값을 가져오기 때문에 JPA에서 엔티티를 조회하지 않아도 값을 알 수 있으며, 다른 select 쿼리가 나가지 않게 되는걸까요?
-
해결됨실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
연관관계 편의 메소드, 생성 메소드에 대해 질문드려요!!
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]안녕하세요. 항상 강의 잘 보고 있습니다. 다름이 아니라 연관관계 편의 메소드와 생성 메소드에 관해 궁금증이 생겨 질문을 드릴려고 합니다. Entity 필드에서 가급적이면 setter 를 지양해야 한다고 알고 있습니다. 그래서 setter 를 쓰지 않고 오직 builder 를 통해 연관관계 편의 메소드와 생성 메소드를 정의할 순 없을까 고민했습니다. 아래는 setter 를 쓰지않고 builder 만 써서 작성해본 코드입니다. <Delivery builder> @Builderprivate Delivery(Order order, Address address, DeliveryStatus deliveryStatus) { this.order = order; this.address = address; this.deliveryStatus = deliveryStatus; } <OrderItem builder> @Builderprivate OrderItem(Order order, Item item, int orderPrice, int orderCount) { this.order = order; this.item = item; this.orderPrice = orderPrice; this.orderCount = orderCount; } <Order builder & createOrder> @Builderprivate Order(Member member, Delivery delivery, List<OrderItem> orderItems, LocalDateTime orderDate, OrderStatus orderStatus) { this.member = member; this.delivery = delivery; this.orderItems = orderItems; this.orderDate = orderDate; this.orderStatus = orderStatus; //== 연관관계 편의 메소드(?) ==// Delivery.builder().order(this).build(); OrderItem.builder().order(this).build(); }//== 생성 메소드 ==//public static Order createOrder(Member member, Delivery delivery, OrderItem... orderItems) { return builder() .member(member).delivery(delivery).orderItems(Arrays.asList(orderItems)).orderDate(LocalDateTime.now()).orderStatus(OrderStatus.ORDER).build(); } 위에서 보시다시피 Delivery 와 OrderItem 에서 builder 를 각각 생성했습니다. 그리고 Order 의 builder 안에 연관관계 편의 메소드(?)를 추가하고, 생성 메소드에서 builder 를 이용하여 order 를 빌드한 후 리턴을 시켜줬습니다. 혹시 이렇게 작성해도 별 문제 없을까요...??? 제 부족한 질문을 읽어주셔서 감사합니다...!
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
orderitem.size 에서 같은 인스턴스(엔티티)가 중복 저장되는 문제
orderItems.size 를 테스트 할때 같은 인스턴스가 orderitem에 중복저장 되는 것 같습니다. 1이 아닌 2가 나와요. List<OrderItem> orderItems = getOrder.getOrderItems(); for(OrderItem orderItem : orderItems) { sout (orderItem); } 하니까 같은 래퍼런스값을 가진 게 2번 똑같이 나왔습니다. 어디서 발생한건지 찾을 수 없어서 질문드려요
-
해결됨실전! 스프링 데이터 JPA
save하고 update할때 혼란이 있습니다
안녕하세요. 초보 개발자 명아주입니다. 궁금한게 있어서 문의드립니다. 제가 공부하다가 놓친걸 수도 있는데 아직 잘 이해가 안되는 부분이 하나 있습니다. 예를들어서 Member member = new Member(); member.setName("hello"); em.persist(member); member.setName("jpa"); 이런 코드가 있을때 예상 : member가 영속성 컨텍스트에 들어감 트랜잭션 종료 때, flush할때 변경감지까지 포함해서 한 번의 쿼리만 나감 insert into member values (1, 'jpa'); 실제 : insert into member values (1, 'hello'); update member set name = 'jpa'; 영속성 컨텍스트에 들어가있다가 아직 플러시 되지 않은 상태에서 변경되면 마지막에 변경된 사항으로 insert 한번만 나갈 줄 알았는데 실제 동작은 insert, 그리고 변경감지에 의한 update가 발생하더라구요. 저번에 말씀하셨던 것중 얼핏 기억나는 스냅샷? 같은 걸로 영속성에 들어간 상태를 스냅샷 찍어놓고 그거에 대한 insert 쿼리가 나가고 그 후에 변경감지를 처리하는건가요?? 궁금합니다! 감사합니다.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
테스트 코드 autowired 질문입니다
안녕하세요. Test 코드에서 public class MemberRepositoryTest { @Autowired MemberRepository memberRepository; 이렇게 돼있던데요. 여기서 @Autowired로 주입을 받아야 하는 이유가 무엇인가요? 그냥 MemberRepository memberRepository = new MemberRepository(); 로 해도 될거같아서 해봤는데 에러가 나더라고요... Member 클래스는 그냥 Member member = new Member(); 이 형태로 쓸 수 있는데, MemberRepository 클래스는 어차피 예제 상황이라 싱글톤으로 안써도 되는 상황인데도 왜 굳이 의존성 주입으로만 해야하는건지 궁금합니다.
-
해결됨스프링 핵심 원리 - 기본편
request 스코프 빈의 HTTP request 구분 질문
안녕하세요. 매번 좋은 강의 잘 듣고 있습니다. request 스코프의 "요청" 구분에 관한 질문이 있어 글 남깁니다. 1. HTTP request 요청이 다른지는 어떻게 판단하나요? 2. 같은 클라이언트가 같은 endpoint(URI)의 요청을 두 번 하였을 경우에도 각각 다른 요청으로 처리되나요?
-
해결됨스프링 핵심 원리 - 기본편
프로토타입 빈에 대한 질문
안녕하세요. 프로토타입 스코프 강의를 듣던 중 궁금점이 생겨 질문 드립니다. 1. 프로토타입 빈의 필요성에 대한 질문 프로토타입 빈은 스프링 컨테이너에서 요청 시마다 새롭게 생성되어 반환된다고 하였습니다. 그렇다면 굳이 스프링 컨테이너에서 관리할 필요가 있나요? 순수 자바코드로도 충분히 가능한 것 아닐까요? 2. 프로토타입 빈의 "관리"에 대한 질문 스프링 컨테이너에서 빈을 생성, 의존관계 주입만 처리하고 이후 관리하지 않는다고 하였는데, 여기서 말하는 '관리'에 해당하는 내용은 어떤 것들이 있는지(정확히는 빈 종료 외에도 다른 항목이 있는지) 궁금합니다. 또한 스프링 컨테이너가 종료될 때 싱글톤타입 빈과는 달리, 프로토타입 빈은 종료되지 않는 건가요?