test 학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] test 강의 내용으로 게시판 만들기를 병행하고 있습니다. 이번 강의에서 Spring Data Jpa로 변경을 하였는데 게시글 수정과 같은 수정 기능은 인터페이스인 SpringDataJpaMemberRepository에서 작성하나요? 아니면 Service단에서 Repository의 find를 통해서 수정하도록 작성하나요? SpringDataJpa에서 find, delete는 있는데 수정은 어떻게 이뤄지는지 궁금합니다..d
안녕하세요. 김영한 선생님의 강의를 참 잘 보고 있는 학생입니다. SQL 중심적인 개발의 문제점 편에서, 객체지향 프로그래밍에서 객체는 자유롭게 객체 그래프를 탐색할 수 있어야하 지만 SQL로 개발하는 경우에는 처음 실행하는 SQL에 따라 탐색 범위가 결정된다 는 문제가 있다고 말씀하셨습니다. 그리고 엄격한 도메인 주도 설계의 관점에서는 '도메인 객체'와 '엔티티 객체'를 분리 해야 한다고 알고 있습니다. 비즈니스 로직을 다루는 도메인 객체가 JPA 라고 하는 기술에 의존하는 것은 영 즐거운 일은 아니기 때문이죠.. ( https://stackoverflow.com/questions/24703756/having-separate-domain-model-and-persistence-model-in-ddd ) 그렇기 때문에 도메인 객체와 엔티티 객체를 분리하게 된다면 Repository 계층에서 예를 들어 findById 를 했을 경우 엔티티 객체를 도메인 객체로 매핑해서 돌려주어야 합니다. 그런데 이럴 경우, 기존의 SQL로 개발하는 경우와 비슷한 문제가 발생하게 되는 것 같습니다. 매핑을 어디까지해서 돌려주어야 하느냐는 점이죠. Member 를 조회했을 때, 객체 그래프 안에 있는 Category까지 싹싹 다 조회해와서 매핑을 해주기도 곤란한 노릇이고, MemberWithTeam , MemberWithOrderAndOrderItem... 와 같은 객체를 따로 따로 만드는 것도 요상해보입니다. 그렇다고 객체 그래프를 다 끊어놓자니 그것도 객체지향적이지 않은 것 같아보이구요.. 이런 상황에서는 어떤 식으로 도메인 객체를 설계하는지, 엔티티 객체의 매핑은 어떤 방법으로 이루어지는지가 너무 궁금합니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예 [질문 내용] 그냥 컨트롤러에서 model에 담아서 조회할떄는 무한루프가 안도는데 json으로 반환할떄는 왜 무한로프 도는지가 궁금합니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 안녕하세요, 영한님! 영한님 수업을 새겨듣고 있는 수강자입니다! 다름이 아니라, JPA 소개파트의 "1차 캐시와 동일성 보장(15분 30초경)" 에서 말씀하신 동일성이 "각 Entity가 참조하는 메모리 주소가 같지 않아도 값을 통해 같음을 보장"한다는 뜻과 일맥상통한 내용인가요? Java의 equals에 대해서 공부하다가 동일성이란 단어가 동일한 의미로 쓰이는지 궁금해서 여쭈어봐요! 만약에 같은 뜻이라면, "같은 엔티티를 반환한다"는 말을 "참조하는 메모리 주소가 같지는 않고, 값만 같은 엔티티를 반환한다"로 이해해도 될까요?? 질문 들어주셔서 감사합니다. 오늘도 좋은 하루 보내세요!!
토비님 안녕하세요. intellij CE 버전에서 spring initializr 로 생성한 프로젝트 실행 시 궁금한게 있습니다. ultimate 버전은 영상에서처럼 run 할 때 우상단에 spring 아이콘이 있고 springboot 플러그인이 적용되어있는데, CE 버전은 그렇지 않고 따로 Run Configurations 가 설정되어있지 않아 아주 동일한 방법으로 실행할 수는 없었습니다. (영상의 "HellobootApplication" 대신 "Current File"로 표시되어있고 실행버튼이 비활성화 되어있습니다.) 일단 main 메소드가 있는 Application.java 파일에서 코드 왼쪽의 실행버튼으로 실행했는데 이렇게 해도 상관 없는건가요? Ultimate 버전과 달리 CE 버전에서 놓치고 가는게 있는지 궁금해서 여쭙니다. 좋은 강의 해주셔서 감사합니다 ~
안녕하세요! 7강 마무리 퀴즈를 스스로 풀어보며 의문점이 생겨 질문 남깁니다. 저는 이런식으로 name 변수를 선언하고 cook() 메소드에 this.name을 활용했는데, 강의에선 기본 생성자와 name을 매개변수로 하는 생성자를 정의하고 풀어 주셨더라구요! 결과는 같게 나오지만 혹시 생성자를 사용하는게 더 좋은 코딩 방법인지, 제가 한 방식이 결과는 맞지만 논리적 오류가 있는지 궁금합니다. 그리고 강의 잘 듣고 있습니다. 감사합니다!
안녕하세요, 강사님. 섹션 9-2, DataSource 자동 구성 클래스에서, connect() 을 테스트하는 코드에서 yml 파일을 이용했을 때, 테스트 실패를 하여 질문글 드립니다. 먼저 강의와 동일하게 properties 파일을 이용한다면 정상적으로 테스트가 통과됩니다. application.properties DataSourceTest 평소에 yml 파일을 더 선호하여, yml 파일로 변경한 후, 테스트 코드 상에서 @TestPropertySource("classpath:/application.yml") 로 classpath 를 properties 에서 yml 로 바꿨을 뿐, 기존과 동일한 환경에서 테스트를 진행해봤습니다. application.yml DataSourceTest 하지만, 아래와 같은 에러 로그가 발생하며 테스트에 실패하게 됩니다. 에러 로그 java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:98) at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:248) at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:138) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$8(ClassBasedTestDescriptor.java:363) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:368) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$9(ClassBasedTestDescriptor.java:363) at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312) at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735) at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:734) at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestInstancePostProcessors(ClassBasedTestDescriptor.java:362) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$instantiateAndPostProcessTestInstance$6(ClassBasedTestDescriptor.java:283) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:282) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:272) at java.base/java.util.Optional.orElseGet(Optional.java:369) at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:271) at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:102) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:101) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:66) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86) at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86) at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53) at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57) at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55) Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tobyspring.config.autoconfig.ServerProperties': Initialization of bean failed; nested exception is org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'server' to tobyspring.config.autoconfig.ServerProperties at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:628) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:920) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:127) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60) at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:276) at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:244) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:141) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:90) ... 71 more Caused by: org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'server' to tobyspring.config.autoconfig.ServerProperties at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:387) at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:347) at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:332) at org.springframework.boot.context.properties.bind.Binder.bindOrCreate(Binder.java:324) at org.springframework.boot.context.properties.bind.Binder.bindOrCreate(Binder.java:293) at org.springframework.boot.context.properties.bind.Binder.bindOrCreate(Binder.java:278) at tobyspring.config.autoconfig.PropertyPostProcessorConfig$1.postProcessAfterInitialization(PropertyPostProcessorConfig.java:30) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:455) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1808) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ... 85 more Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [tobyspring.config.autoconfig.ServerProperties] at org.springframework.boot.context.properties.bind.BindConverter.convert(BindConverter.java:118) at org.springframework.boot.context.properties.bind.BindConverter.convert(BindConverter.java:100) at org.springframework.boot.context.properties.bind.BindConverter.convert(BindConverter.java:92) at org.springframework.boot.context.properties.bind.Binder.bindProperty(Binder.java:459) at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:403) at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343) ... 93 more 에러 로그를 확인한 후, ServerProperties 가 제대로 바인딩 되지 않음을 확인하였습니다. 바인딩이 테스트 환경이 아닌, 일반 서버를 구동할 때도 제대로 안되는건가? 라는 의구심에 로그를 찍어보며 이를 확인해봤습니다. 로그 출력 PropertyPostProcessorConfig TomcatWebServerConfig DataSourceConfig 로그 출력 확인 (일반 서버 구동) 테스트 환경이 아닌 일반 서버를 실행시, 위의 결과와 마찬가지로 제대로 바인딩됨을 확인하였습니다. 따라서, 테스트 코드상에서 바인딩이 제대로 이뤄지지 않음을 알게 되었고, 스프링부트 레퍼런스를 찾아보니 yml 파일은 @PropertySource 와 @TestPropertySource 를 통해 로딩되지 않음을 확인하였습니다. ( https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#boot-features-external-config-yaml-shortcomings ) 이를 해결하기 위해, 구글링을 통해 해결방법을 참고하여 아래와 같이 변경하였더니, 테스트가 제대로 통과됨을 확인하였습니다. (참고링크 : https://www.inflearn.com/questions/293325/testpropertysource%EC%A7%88%EB%AC%B8%EC%9E%85%EB%8B%88%EB%8B%A4 ) 하지만 이전 토비님의 질문 답변 중, @SpringBootTest 와 @ExtendWith + @ContextConfiguration 의 차이점에 대한 글을 보게 되었습니다. ( https://www.inflearn.com/questions/834733/springboottest%EC%99%80-extendwith-contextconfiguration-%EC%B0%A8%EC%9D%B4%EA%B0%80-%EA%B6%81%EA%B8%88%ED%95%A9%EB%8B%88%EB%8B%A4 ) 혹시 @ExtendWith + @ContextConfiguration 을 유지한 채, yml 파일을 이용하여 해당 테스트를 통과할 수 있는 방법이 존재하는지 궁금합니다. 항상 수준 높은 강의에 감사드립니다.
p6spy releases를 확인해보면 1.9.0부터 Spring boot 3을 지원한다고 되어있고 테스트시 로그가 안뜹니다. 다른 질문에서보니 해당 버전이 메이븐에서만 지원되어서 그런 듯 합니다. 그래서 바로 아래 버전인 1.8.1을 사용해서 정상적으로 로그가 뜨는 것을 확인했습니다. 그래서 앞으로 최신 버전으로 했을때 안뜬다면 버전을 내려보시면 좋을 것 같습니다.
지난번에 말씀해주신 부분들은 다 수정 처리 해서 했는데 이번에 jdbc를 연결하면서 이상하게 build.gradle도 다시 재실행하고 h2 관련 디펜던시도 다 적용을 했는데, 서버 자체는 잘 실행되는데 DataSourceTest가 지금 실행이 안되서 이렇게 질문드립니다. 뭔가 connect를 잘 못불러오는거 같은데 봐주시면 감사합니다! 깃허브 주소는 https://github.com/ted7088/hellospring_toby_study 입니다...
앞서 수강생처럼 contextPath 부분이 value를 잘 읽어오지 못해서 질문드립니다... PropertyPlaceHolderConfig를 추가하고 META-INF에도 추가를 했는데 contextPath 값을 그대로 가져오지 못해서 이렇게 질문드립니다. 깃허브 링크 남겨드립니다. 감사합니다! https://github.com/ted7088/hellospring_toby_study
제가 강의 들으면서 공부할때 매번 깃에다 올리고 커밋 후 푸시 하는 작업을 통해 두대의 컴퓨터에서 작업을 진행했는데, 색션 7,8을 어느 한 컴퓨터에서 듣고 다른컴퓨터에서 깃에서 프로젝트 업데이트 하니깐 hellobootapplication 이 실행이 안됩니다... 오류 사항은 Description: Web application could not be started as there was no org.springframework.boot.web.servlet.server.ServletWebServerFactory bean defined in the context. Action: Check your application's dependencies for a supported servlet web server. Check the configured web application type. 종료 코드 1(으)로 완료된 프로세스 이렇게 나오는데 혹시 이유를 알 수 있을까요? 깃에서 가져와서 그런지 HellobootApplication에 환경변수를 추가해도 이상하게 안되더라고요... 기존에 한컴퓨터는 실행이 지금도 잘되는데 다른컴퓨터에서는 이런 오류가 걸려서 질문드립니다
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 안녕하세요. 카운트 쿼리 분리 부분을 듣는 도중에 카운트 쿼리에 LEFT JOIN이 사용되는 결과를 확인하기 위해 다음처럼 코드를 작성하였습니다. public interface MemberRepository extends JpaRepository<Member, Long> { @Query(value = "select m from Member m left join m.team t") Page<Member> findByAge(int age, Pageable pageable); ... } @Test public void paging() throws Exception { //given memberRepository.save(new Member("member1", 10)); memberRepository.save(new Member("member2", 10)); memberRepository.save(new Member("member3", 10)); memberRepository.save(new Member("member4", 10)); memberRepository.save(new Member("member5", 10)); //when PageRequest pageRequest = PageRequest.of(0, 3, Sort.by(Sort.Direction.ASC, "username")); Page<Member> page = memberRepository.findByAge(10, pageRequest); //then List<Member> content = page.getContent(); assertThat(content.size()).isEqualTo(3); assertThat(page.getTotalElements()).isEqualTo(5); assertThat(page.getNumber()).isEqualTo(0); assertThat(page.getTotalPages()).isEqualTo(2); assertThat(page.isFirst()).isTrue(); assertThat(page.hasNext()).isTrue(); } 그런데 결과는 강의와는 달리 카운트 쿼리에 LEFT JOIN 이 사용되지 않았고, 심지어 JPQL select m from Member m left join m.team t 을 @Query에 작성했음에도 조회 쿼리도 LEFT JOIN을 사용하지 않은 것을 확인했습니다. 이후 스프링 부트 3 이하 버전에서 동일한 코드로 실행해보니 강의와 동일한 결과를 얻을 수 있었습니다. 스프링 부트 3 부터 적용된 스프링 데이터 JPA 에서는 이러한 부분의 최적화를 자동으로 제공하는 것일까요?
안녕하세요. 백엔드 개발자 희망하고 있습니다. 자바 독학 공부 시작했는데 기본문법 예제들은 혼자 짤 수 있는데 객체지향/3 로또 부분부터 어렵네요. 구구단, 별찍기 하다가 로또 구현할 수 있을때까지 공부 방법이 궁금합니다. ㅠ.ㅠ 자바 공부 방법 알려주세요 ㅠㅠㅠ 지금은 강사님 강의 보고 이해가 부족하다는 부분 이론서 보면서 나가고있습니다. 이론서에 나와있는 문제들도 타이핑 하면서 진행하구 있습니다. 길게 코드 작성할 수 있을때까지 자바 공부 방법 알려주세요.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] plugins { id 'org.springframework.boot' version '2.6.5' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' ext["hibernate.version"] = " 5.6.5.Final " configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'javax.validation:validation-api' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5' //JdbcTemplate 추가 //implementation 'org.springframework.boot:spring-boot-starter-jdbc' //MyBatis 추가 implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0' //JPA, 스프링 데이터 JPA 추가 implementation 'org.springframework.boot:spring-boot-starter-data-jpa' //Querydsl 추가 implementation 'com.querydsl:querydsl-jpa' annotationProcessor "com.querydsl:querydsl-apt:$ { dependencyManagement.importedProperties['querydsl.version'] } :jpa" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" //H2 데이터베이스 추가 runtimeOnly 'com.h2database:h2' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' //테스트에서 lombok 사용 testCompileOnly 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' } tasks.named('test') { useJUnitPlatform() } //querydsl 추가 //def querydslDir = '$buildDir/generated' def querydslDir = "src/main/generated" //clean { // delete file(generated) //} querydsl { library = "com.querydsl:querydsl-apt" jpa = true querydslSourcesDir = querydslDir } sourceSets { main { java { srcDirs = ['src/main/java', querydslDir] } } } compileQuerydsl { options.annotationProcessorPath = configurations.querydsl } configurations { querydsl.extendsFrom compileClasspath } 강사님이 올려주신 내용 + 구글링 + 직접 수정했습니다. 간혹, 빌드는 되는데 generated 파일에 QClass 안보이시는 분들은 queryDsl 저장되는 경로에 $buildDir 대신 'src/main/'으로 해보세요
주문 서비스 개발 부분 강의를 듣다가 궁금한 점이 있어 질문드립니다. 주문 취소(OrderService.cancelOrder) 부분에서order.cancel() 만 작성하면 JPA 특징으로 인해, 데이터 업데이트 관련 쿼리 로직 없이 자동으로 업데이트 된다고 하셨는데요. 주문 생성(OrderService.order)의 EntityManager 가 사용된 orderRepository.save (order); 와 혼동이 와서 질문 남깁니다. 주문 취소 order.cancel() 메서드를 타면서 엔티티의 값(status, count 등) 변경 내역이 자동으로 업데이트 되는 것이라고 하면, 주문 생성도 Order.createOrder(member, delivery, orderItem); 를 타면서 엔티티의 값들을 설정하기 때문에 orderRepository.save (order); 를 사용하지 않아도 되는게 아닌가 라는 생각이 듭니다. 제가 JPA 를 잘 몰라서 혼란이 오는 것 같은데.. 쿼리는 직접 작성하지 않아도 업데이트/저장/삭제 등 DB 조작이 일어나려면 EntityManager 를 통해야 된다고 생각하고 있었습니다. 주문 취소는 EntityManager 없이 업데이트 되고, 주문 생성은 EntityManager의 persist() 를 사용해서 저장하는 것 이 2가지 차이점에 대해서 설명 부탁드립니다! 감사합니다 :)
안녕하세요. where 조건을 동적으로 생성해주는 부분에 대해서는 충분히 이해가 되었습니다. 그런데 혹시 특정 condition 값에 따라 join을 해줘야하는 테이블이 다른 경우라면 어떻게 처리되어야 할지 모르겠어서 글을 남기게 되었습니다. condition조건에 teamName이 있을 때만 team을 조인해주고 싶은데 join 구문을 동적으로 처리할 수 있는 좋은 방법이 어떤 것인지 질문드립니다. 😭 감사합니다.