package kdy.board.article.api; import MSA.board.article.service.response.ArticleResponse; import lombok.AllArgsConstructor; import lombok.Getter; import org.junit.jupiter.api.Test; import org.springframework.web.client.RestClient; public class ArticleApiTest { RestClient restClient = RestClient.create("http://localhost:9000"); @Test void createTest() { ArticleResponse response = create(new ArticleCreateRequest( "hi", "my content", 1L, 1L )); System.out.println("response = " + response); } ArticleResponse create(ArticleCreateRequest request) { return restClient.post() .uri("/v1/articles") .body(request) .retrieve() .body(ArticleResponse.class); } @Getter @AllArgsConstructor static class ArticleCreateRequest { private String title; private String content; private Long writerId; private Long boardId; } @Getter @AllArgsConstructor static class ArticleUpdateRequest { private String title; private String content; } } 위와 같이 코드 쓰고 Test를 진행하면 아래와 같은 에러가 뜹니다. cmd창에서 검색해봐도 현재 9000을 쓰고 있는 서버는 없다고 뜨는데 어느 부분이 문제인 건가요? > Task :common:snowflake:compileJava UP-TO-DATE > Task :common:snowflake:processResources NO-SOURCE > Task :common:snowflake:classes UP-TO-DATE > Task :common:snowflake:jar UP-TO-DATE > Task :service:article:compileJava UP-TO-DATE > Task :service:article:processResources UP-TO-DATE > Task :service:article:classes UP-TO-DATE > Task :service:article:compileTestJava > Task :service:article:processTestResources NO-SOURCE > Task :service:article:testClasses org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:9000/v1/articles": null at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.createResourceAccessException(DefaultRestClient.java:575) at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchangeInternal(DefaultRestClient.java:498) at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.retrieve(DefaultRestClient.java:460) at kdy.board.article.api.ArticleApiTest.create(ArticleApiTest.java:24) at kdy.board.article.api.ArticleApiTest.createTest(ArticleApiTest.java:14) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at java.base/java.util.ArrayList.forEach(ArrayList.java:1596) at java.base/java.util.ArrayList.forEach(ArrayList.java:1596) Caused by: java.net.ConnectException at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:951) at java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:133) at org.springframework.http.client.JdkClientHttpRequest.executeInternal(JdkClientHttpRequest.java:102) at org.springframework.http.client.AbstractStreamingClientHttpRequest.executeInternal(AbstractStreamingClientHttpRequest.java:70) at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66) at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchangeInternal(DefaultRestClient.java:492) ... 6 more Caused by: java.net.ConnectException at java.net.http/jdk.internal.net.http.common.Utils.toConnectException(Utils.java:1041) at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:227) at java.net.http/jdk.internal.net.http.PlainHttpConnection.checkRetryConnect(PlainHttpConnection.java:280) at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$2(PlainHttpConnection.java:238) at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934) at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911) at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1773) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base/java.lang.Thread.run(Thread.java:1583) Caused by: java.nio.channels.ClosedChannelException at java.base/sun.nio.ch.SocketChannelImpl.ensureOpen(SocketChannelImpl.java:202) at java.base/sun.nio.ch.SocketChannelImpl.beginConnect(SocketChannelImpl.java:786) at java.base/sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:874) at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$1(PlainHttpConnection.java:210) at java.base/java.security.AccessController.doPrivileged(AccessController.java:571) at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:212) ... 9 more java.net.ConnectException at java.net.http/jdk.internal.net.http.HttpClientImpl.send(HttpClientImpl.java:951) at java.net.http/jdk.internal.net.http.HttpClientFacade.send(HttpClientFacade.java:133) at org.springframework.http.client.JdkClientHttpRequest.executeInternal(JdkClientHttpRequest.java:102) at org.springframework.http.client.AbstractStreamingClientHttpRequest.executeInternal(AbstractStreamingClientHttpRequest.java:70) at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66) at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchangeInternal(DefaultRestClient.java:492) at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.retrieve(DefaultRestClient.java:460) at kdy.board.article.api.ArticleApiTest.create(ArticleApiTest.java:24) at kdy.board.article.api.ArticleApiTest.createTest(ArticleApiTest.java:14) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at java.base/java.util.ArrayList.forEach(ArrayList.java:1596) at java.base/java.util.ArrayList.forEach(ArrayList.java:1596) Caused by: java.net.ConnectException at java.net.http/jdk.internal.net.http.common.Utils.toConnectException(Utils.java:1041) at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:227) at java.net.http/jdk.internal.net.http.PlainHttpConnection.checkRetryConnect(PlainHttpConnection.java:280) at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$2(PlainHttpConnection.java:238) at java.base/java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:934) at java.base/java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:911) at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1773) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base/java.lang.Thread.run(Thread.java:1583) Caused by: java.nio.channels.ClosedChannelException at java.base/sun.nio.ch.SocketChannelImpl.ensureOpen(SocketChannelImpl.java:202) at java.base/sun.nio.ch.SocketChannelImpl.beginConnect(SocketChannelImpl.java:786) at java.base/sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:874) at java.net.http/jdk.internal.net.http.PlainHttpConnection.lambda$connectAsync$1(PlainHttpConnection.java:210) at java.base/java.security.AccessController.doPrivileged(AccessController.java:571) at java.net.http/jdk.internal.net.http.PlainHttpConnection.connectAsync(PlainHttpConnection.java:212) ... 9 more > Task :service:article:test ArticleApiTest > createTest() FAILED org.springframework.web.client.ResourceAccessException at ArticleApiTest.java:24 Caused by: java.net.ConnectException at ArticleApiTest.java:24 Caused by: java.net.ConnectException at Utils.java:1041 Caused by: java.nio.channels.ClosedChannelException at SocketChannelImpl.java:202 1 test completed, 1 failed > Task :service:article:test FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':service:article:test'. > There were failing tests. See the report at: file:///D:/projects/MSA-board/service/article/build/reports/tests/test/index.html * Try: > Run with --scan to get full insights. BUILD FAILED in 9s 6 actionable tasks: 2 executed, 4 up-to-date
위와 같이 로그가 찍혔으면, DLQ에서 ack 상태가 되어야하는것 아닐까요? @RabbitListener(queues = RabbitMQConfig.DLQ) public void process(String message) { System.out.println("DLQ Message Received: " + message); try { String fixMessage = "success"; rabbitTemplate.convertAndSend( RabbitMQConfig.ORDER_EXCHANGE, "order.completed.shipping", fixMessage ); System.out.println("DLQ Message Sent: " + fixMessage); } catch (Exception e) { System.err.println("### [DLQ Consumer Error] " + e.getMessage()); } } 위의 코드인 경우 AUTO 모드로 동작해서 자동으로 DLQ에서 처리가 되면 ACK 을 받을 것이라 생각했는데, DLQ에서 unack 상태로 남아있어서 여쭤봅니다! 이후에 애플리케이션을 종료하면 DLQ에서는 다시 ready 상태가 되고, 애플리케이션을 실행하면 이를 실행하고 와 같이 로그가 찍힌 다음에 다시 unack 상태가 됩니다. 좋은 강의 감사드립니다 :)
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] @Transactional public void updateItem(Long id, String name, int price, int stockQuantity) { Item item = itemRepository.findOne(id); item.setName(name); item.setPrice(price); item.setStockQuantity(stockQuantity); } 여기서 @Transactional 이 없으면 변경감지 로직이 발생하지 않나요? @Transactional 은 두개이상의 쿼리를 하나의 논리적인 단위로 묶어줄때 사용하는 것으로 알고 있는데 이 상황에서도 변경감지를 실행하기 위해 반드시 호출해주어야하나요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 준영속이란 한번은 영속상태였지만, 현재는 영속성 컨텍스트의 관리 대상이 아닌 엔티티인데 db 에 저장될떄 pk 가 생기기 떄문에 객체에 식별자가 있으면 무조건 준영속 엔티티인가요? 엔티티매니저에서 꺼내서 Detached되어 식별자가 셋팅되거나 아니면 새로운 객체에 id 값만 셋팅되어 있으면 준영속 상태볼 수 있나요? 왜 준영속 상태는 따로 있나요? 비영속만 있어도 되지않나요? 무슨 이점이 있나요?
알려주신데로 UserControllerV1.java에 어노테이션 추가하고 재기동한 뒤 검색 했는데...로그에 com.auth0.jwt.exceptions.JWTDecodeException: The token was expected to have 3 parts, but got 1. 이런 에러가 나옵니다.ㅠㅠ 개발자 도구에는 아래와 같은 에러가 나옵니다. UserControllerV1.java는 이렇게 작성되어 있습니다. 어떤 부분을 더 확인해야 하는지, 어떤 부분이 문제 인건지 확인 부탁드립니다.ㅠㅠ **추가로 에러내용 전체입니다. com.auth0.jwt.exceptions.JWTDecodeException: The token was expected to have 3 parts, but got 1. at com.auth0.jwt.TokenUtils.splitToken(TokenUtils.java:21) ~[java-jwt-3.12.0.jar!/:3.12.0] at com.auth0.jwt.JWTDecoder.<init>(JWTDecoder.java:36) ~[java-jwt-3.12.0.jar!/:3.12.0] at com.auth0.jwt.JWTDecoder.<init>(JWTDecoder.java:32) ~[java-jwt-3.12.0.jar!/:3.12.0] at com.auth0.jwt.JWT.decode(JWT.java:45) ~[java-jwt-3.12.0.jar!/:3.12.0] at com.example.demo.security .JWTProvider.decodedJWT(JWTProvider.java:109) ~[!/:0.0.1-SNAPSHOT] at com.example.demo.security .JWTProvider.getUserFromToken(JWTProvider.java:123) ~[!/:0.0.1-SNAPSHOT] at com.example.demo.domain.user.controller.UserControllerV1.searchUser(UserControllerV1.java:43) ~[!/:0.0.1-SNAPSHOT] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na] at org.springframework.web.method.support .InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:255) ~[spring-web-6.1.13.jar!/:6.1.13] at org.springframework.web.method.support .InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:188) ~[spring-web-6.1.13.jar!/:6.1.13] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.1.13.jar!/:6.1.13] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926) ~[spring-webmvc-6.1.13.jar!/:6.1.13] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831) ~[spring-webmvc-6.1.13.jar!/:6.1.13] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.13.jar!/:6.1.13] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.13.jar!/:6.1.13] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.13.jar!/:6.1.13] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.13.jar!/:6.1.13] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[spring-webmvc-6.1.13.jar!/:6.1.13] at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.13.jar!/:6.1.13] at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.30.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.13.jar!/:6.1.13] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.13.jar!/:6.1.13] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.1.13.jar!/:6.1.13] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.13.jar!/:6.1.13] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.1.13.jar!/:6.1.13] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.13.jar!/:6.1.13] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:384) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:905) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.tomcat.util.net .NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.tomcat.util.net.SocketProcessorBase.run (SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.tomcat.util.threads.ThreadPoolExecutor$ Worker.run (ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.30.jar!/:na] at org.apache.tomcat.util.threads.TaskThread$ WrappingRunnable.run (TaskThread.java:63) ~[tomcat-embed-core-10.1.30.jar!/:na] at java.base/ java.lang.Thread.run (Thread.java:833) ~[na:na]
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] erd 설계를 하다가 스스로 의문이 조금 들어서 질문드립니다. 현재 다음과 같은 앱을 구상하고 있습니다. AI 모델과 연동해서 추천 시스템을 생각 중인데 도메인 설계에 대해서 궁금한 부분이 생겨서 질문드립니다. package forpracticejunbao.junbaoprac_be.recommend.domain; import forpracticejunbao.junbaoprac_be.user.domain.User; import forpracticejunbao.junbaoprac_be.common.util.BaseEntity; import jakarta.persistence.*; import lombok.*; import java.util.ArrayList; import java.util.List; @Table(name = "recommend") @Entity @Getter @NoArgsConstructor @AllArgsConstructor @Builder public class Recommend extends BaseEntity { @Id @Column(name = "recommend_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id", nullable = false) private User user; @OneToMany(mappedBy = "recommend",cascade = CascadeType.ALL, orphanRemoval = true) @Builder.Default private List<RecommendClusterOption> recommendClusterOptions = new ArrayList<>(); @OneToMany(mappedBy = "recommend",cascade = CascadeType.ALL, orphanRemoval = true) @Builder.Default private List<RecommendValueOption> recommendValueOptions = new ArrayList<>(); @OneToMany(mappedBy = "recommend",cascade = CascadeType.ALL, orphanRemoval = true) @Builder.Default private List<RecommendResult> results = new ArrayList<>(); public void updateRecommendClusterOptions(List<RecommendClusterOption> recommendClusterOptions) { if (this.recommendClusterOptions != null) { this.recommendClusterOptions.clear(); this.recommendClusterOptions.addAll(recommendClusterOptions); } else { this.recommendClusterOptions = recommendClusterOptions; } } public void updateRecommendValueOptions(List<RecommendValueOption> recommendValueOptions) { if (this.recommendValueOptions != null) { this.recommendValueOptions.clear(); this.recommendValueOptions.addAll(recommendValueOptions); } else { this.recommendValueOptions = recommendValueOptions; } } } Recommend 클래스를 만들고, ClusterOption(클러스터 선택)과 ValueOption(계절, 요일 등등)을 일대다 다대일로 풀고자 했는데 이 두가지 엔티티가 크게 다르지 않은 것 같아서 그냥 하나로 합치는게 좋을지(그냥 enum으로만 구분) 아니면 의미적으로 좀 다르기 때문에 구분하는게 좋을지 궁금합니다.(클러스터 선택과 계절 선택은 하나만 선택 가능, 나머지는 하나 이상 선택 가능 조건이기에 클러스터와 계절을 도메인으로 묶을지도 살짝 고민이 되는 것 같습니다..) 결과를 RecommendResult로 보여주고자하는데(ai 추천 받은 top 5값에 대한 스팟 정보 제공 목적) 괜찮은 설계일지 궁금합니다. init.sql을 통해 클러스터, 계절, 요일 등 초기값들을 insert 해주고, spot 정보는 csv 파일로 부터 읽어오도록 구현하고 있는데(@PostConstruct, implementation 'com.opencsv:opencsv:5.5' 이용) 실제로 이런 설계에서 초기값을 주입하고 이후 로직 구현하는게 실무적으로 일반적인 방식인지 궁금합니다..! 긴 글 읽어주셔서 감사합니다.
- 학습 관련 질문을 남겨주세요. 구체적으로 적을수록 좋아요! - 마크다운과 단축키를 활용하면 글을 더 편하게 작성할 수 있어요. - 커뮤니티 질문 & 답변에 비슷한 내용이 있었는지 먼저 검색해보세요. - 서로 예의를 지키며 존중하는 분위기를 함께 만들어가요. - 잠깐! 인프런 서비스 관련 문의는 1:1 문의하기를 이용해 주세요
안녕하세요 ! 개발환경세팅에서 선생님이 하시는 과정을 그대로 따라 갔는데 npm run serve 명령어 입력 시 밑에 오류가 뜹니다. 검색해보니 pnpm을 설치하라고 하는데 선생님과 똑같이 진행 했는데 오류가 뜨는 이유가 뭔지 궁금해서 질문글 남깁니다. 오류 내용: ERROR Error: The project seems to require pnpm but it's not installed. Error: The project seems to require pnpm but it's not installed.
안녕하세요 선생님 ! 섹션 6. 이전 메시지 조회 강의에서 질문 있습니다. 1. 선생님 코드의 getChatHistory() 메서드에서 chatParticipants를 chatRoom으로 조회해서 for문을 돌면서 현재 로그인한 멤버가 chatParticipants에 있는지 확인하고 있는데, findByChatRoomAndMember 메서드를 통해 참여자인지 확인해도 로직에 상관이 없을까요 ? 2. 현재 로직은 getHistory 메서드가 실행되면 해당 참여자가 채팅방에 참여하기 전의 메시지들까지 전부 표시될것 같은데, 참여자가 채팅방에 참여한 후 부터의 메시지만 보여주고 싶으면 참여시간을 따로 저장한 다음 findByChatRoomAndCreatedTimeGreaterThanEqualOrderByCreatedTimeAsc( ChatRoom chatRoom, LocalDateTime participatedTime); 이런식으로 코드를 짜면 될까요 ? 좋은 방법인지 모르겠습니다. 선생님 코드 public List<ChatMessageDto> getChatHistory(Long roomId){ // 내가 해당 채팅방의 참여자가 아닐경우 에러 ChatRoom chatRoom = chatRoomRepository.findById(roomId).orElseThrow(()-> new EntityNotFoundException("room cannot be found")); Member member = memberRepository.findByEmail(SecurityContextHolder.getContext().getAuthentication().getName()).orElseThrow(()->new EntityNotFoundException("member cannot be found")); List<ChatParticipant> chatParticipants = chatParticipantRepository.findByChatRoom(chatRoom); boolean check = false; for(ChatParticipant c : chatParticipants){ if(c.getMember().equals(member)){ check = true; } } if(!check)throw new IllegalArgumentException("본인이 속하지 않은 채팅방입니다."); // 특정 room에 대한 message조회 List<ChatMessage> chatMessages = chatMessageRepository.findByChatRoomOrderByCreatedTimeAsc(chatRoom); List<ChatMessageDto> chatMessageDtos = new ArrayList<>(); for(ChatMessage c : chatMessages){ ChatMessageDto chatMessageDto = ChatMessageDto.builder() .message(c.getContent()) .senderEmail(c.getMember().getEmail()) .build(); chatMessageDtos.add(chatMessageDto); } return chatMessageDtos; }
학습 관련 질문을 최대한 상세히 남겨주세요! 고민 과정도 같이 나열해주셔도 좋습니다. 먼저 유사한 질문이 있었는지 검색해보세요. 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. [인기글 Producer&Consumer 테스트] 강의 6분 30초에서 좋아요 수는 userId는 유니크해야 좋아요 수가 중복없이 하나씩으로 집계된다고 말씀하셨습니다. 근데 비관적 락 방법 1과 2 그리고 낙관적 락 방법 모두 다 저희가 구현할 때, 따로 userId에 대한 중복 처리는 하지 않았는데 userId는 동일해도 상관 없지 않나 싶어서요. 비관적 락 방법 1 쿼리도 단순 where 조건은 articleId 뿐이라서 질문드려봅니다. 게시글 조회수는 redis로 key 생성할때, articleId와 userId를 활용해서 중복처리는 했는데, 게시글 좋아요수는 redis를 활용하지 않아서요!
학습 관련 질문을 최대한 상세히 남겨주세요! 고민 과정도 같이 나열해주셔도 좋습니다. 먼저 유사한 질문이 있었는지 검색해보세요. 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. mysql 말고 마리아 디비로 진행하고 있는데 다음과 같은 오류가 납니다... java.sql.SQLException: (conn=47) Record has changed since last read in table 'article_like_count' 그래서 인지 count가 일정하지 않네요.. 이유가 있을까요
안녕하세요. 강의 잘 듣고 있습니다! restClient 사용시에 retrieve ignore로 테스트가 계속 실패 되네요. void인 경우 body(Void.class)하면 됐었는데 likePerformance 하는 경우 실패가 계속 되버려서요. 500에러라면서. body를 제거하고 하면 test 실패이고 해결방법 있을까요?
게시글 데이터 삽입 부분에서요, 영상 강의에서는 데이터 1200만건 삽입 하는데 대략 13분 정도 걸리는걸 확인 햇는데, 저는 2초만에 끝나더니 삽입된 갯수 확인해보니까 2만건만 추가 되고 더 추가 안된거같은데 어떤 문제가 있을가요?? 아래는 코드랑 영상에서 설명한 sql 설정값 첨부 했습니다. @SpringBootTest public class DataInitializer { @PersistenceContext EntityManager entityManager; @Autowired TransactionTemplate transactionTemplate; Snowflake snowflake = new Snowflake(); CountDownLatch latch = new CountDownLatch(EXECUTE_COUNT); static final int BULK_INSERT_SIZE = 2000; static final int EXECUTE_COUNT = 6000; @Test void initialize() throws InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(10); for(int i = 0; i < EXECUTE_COUNT; i++) { executorService.submit(() -> { insert(); latch.countDown(); System.out.println("latch.getCount() = " + latch.getCount()); }); } latch.await(); executorService.shutdown(); } void insert() { transactionTemplate.executeWithoutResult(status -> { for(int i = 0; i < BULK_INSERT_SIZE; i++) { Article article = Article.create( snowflake.nextId(), "title" + i, "content" + i, 1L, 1L ); entityManager.persist(article); } }); } }
댓글의 path를 설정하는 과정에서 public CommentPath createChildCommentPath(String descendantsTopPath) { if (descendantsTopPath == null) { return CommentPath.create(path + MIN_CHUNK); } String childrenTopPath = findChildrenTopPath(descendantsTopPath); return CommentPath.create(increase(childrenTopPath)); } 이런식으로 findChildrenTopPath 를 설정하게 되는데 이 과정에서 동시성 이슈가 발생할 수 있을 것 같아 질문 드립니다. increase 하는 함수에서도 동시성 제어를 하는 파트가 없어 동시에 같은 계층의 댓글이 생성되면 id가 겹칠 것 같습니다!