묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술
webapp/jsp/members.jsp
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. webapp/jsp/members.jsp는 어디서 불러와지는 건가요 ?webapp/jsp/members/new-form.jsp나 webapp/jsp/members/save.jsp에는 members.jsp를 가져오는 코드가 존재하지 않는데member.jsp는 어디에서 호출이 되는건지 궁금합니다.
-
해결됨3. 웹개발 코스 [Enterprise Architecture(EA) X 전자정부프레임워크]
전자정부프레임워크를 MS-SQL과 어떻게 연동하나요?
전자정부프레임워크를 MS-SQL과 어떻게 연동하는지 메일로 문의를 드렸는데 게시판에 글쓰기도 전에 예제를 올려 주셨네요. ^^감사합니다.
-
미해결스프링 MVC 2편 - 백엔드 웹 개발 활용 기술
질문
질문
-
미해결자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]
24강 듣고있는데
맥북 인텔리제이 커뮤쓰고있는 사람입니다!@GeneratedValue 하고뭘해도 빨간줄이 안뜨는데 정상일까요?? private long id = null;해줘도 빨간줄이안뜨네요 ㅠㅠ
-
미해결스프링 핵심 원리 - 기본편
초기화, 소멸 인터페이스의 단점에서 질문
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]초기화, 소멸 인터페이스의 단점부분에서 아래의 내용이 언급 되었습니다. 내가 코드를 고칠 수 없는 외부 라이브러리에 적용할 수 없다클래스파일로 컴파일되어있는 수정이 불가한 라이브러리를 받았다고 가정해보자. 이 라이브러리의 초기화와 종료 메서드를 무조건 호출 해주어야 한다. 스프링 빈으로 이미 등록 했는데 우리는 코드를 고칠 방법이 없다. 위에 주어진 예시가 잘 이해가 안가서 좀 더풀어서 설명 가능하실까요?
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
커넥션의 개수가 의미하는게 뭔지 헷갈립니다!
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 커넥션 풀이라는 개념이 미리 DB와 연결하여 받은 세션을 저장해 다음에 DB에 SQL로 요청을 할 때 빠르게 하기 위함이라는 것 까지는 이해했는데그렇다면 커넥션의 개수가 의미하는거는 어떤건가요?? 10개의 커넥션이 있다면 10명의 사용자까지 동시에 DB에 접근할 수 있다는 의미인가요??
-
해결됨스프링 핵심 원리 - 기본편
required = false 에 대해서 질문드립니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)예[질문 내용] @Autowired(required = true) public void setNoBean1(Member noBean1){ System.out.println("noBean1 = " + noBean1); } 해당 코드에서 오류가 나는 이유가 Member가 빈으로 등록되어있지 않아서 자동 주입할 대상이 없어서 나는 오류라고 하셨는데 그렇다면 Nullable,OPtional은 스프링 자체적으로 무엇인가 처리해준다고 보면 되는것일까요?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
insert 쿼리는 로깅이 되지 않습니다. (수정 -> 원인 파악 완료)
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]질문 수정테스트 코드에 @Rollback(value = false) 어노테이션을 넣고 실행했더니 INSERT 쿼리도 로깅되는 것을 확인했습니다!!생각해 보니, 롤백이 되지 않으면 그때 한 번에 쿼리를 보내는 것이 자연스러운 것 같네요..! 롤백될 쿼리까지 로그에 남으면 개발자 입장에서 원인을 파악하기 더 힘들 것 같고요.원래 롤백이 되는 쿼리는 로깅이 안 되는 것이 정상인 거겠죠?? 기존 질문위 사진과 같이 create table 쿼리는 로깅이 잘 되지만, insert 쿼리는 로깅이 되지 않습니다!이유가 무엇인지 알 수 있을까요??관련 코드 및 로그 첨부하겠습니다.application.yml 설정spring: datasource: url: jdbc:h2:tcp://localhost/~/Programming/h2/jpashop username: sa password: driver-class-name: org.h2.Driver jpa: hibernate: ddl-auto: create properties: hibernate: show_sql: true format_sql: true logging: level: org.hibernate.sql: debug 실행한 테스트 코드@Test @Transactional void testMember() { // given final Member member = new Member(); member.setUsername("memberA"); // when final Long savedId = memberRepository.save(member); final Member findMember = memberRepository.find(savedId); // then assertThat(findMember.getId()).isEqualTo(member.getId()); assertThat(findMember.getUsername()).isEqualTo(member.getUsername()); assertThat(findMember).isEqualTo(member); }로그(원인을 파악하여, 글이 길어지지 않기 위해 로그는 첨부하지 않겠습니다.)
-
해결됨스프링 핵심 원리 - 기본편
싱글톤 문제점: DIP 위반
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]제목의 키워드에 관한 질문글들을 읽으면서 의문이 생겨 질문드립니다. 먼저 제가 질문글들을 읽고 이해하고있는 내용은 다음과 같습니다.싱글톤을 사용한다하여 무조건 DIP를 위반하는 것이 아니다. AppConfig를 사용하면 DIP위반을 피할 수 있다. 즉, 클라이언트에서 getInstance로 싱글톤 객체를 직접 참조하는 것이 아닌, 외부에서 getInstance로 반환된 싱글톤 객체를 의존성 주입을 받아 사용하면 DIP를 준수 할 수 있다.그런데 이렇게 이해를 하니 DIP를 위반하는 것은 싱글톤을 사용함에 따라 생기는 문제가 아닌 의존성주입을 사용하지 않음에 따라 생기는 문제인것 같다는 의문이 생깁니다."의존관계상 클라이언트가 구체 클래스에 의존한다"라고 되어있는데, 기존에 역할에만 잘 의존하고 있던 클라이언트가 구현체가 싱글톤으로 바뀜에 따라 역할이 아닌 구체에 의존해야만하는 강제적인 상황이 발생하는 경우가 존재하는건가요?
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
V1: 엔티티 직접노출 질문입니다.
@JsonIgnore는 양방향 관계의 무한루프를 막기 위해 설정하는 것이고, @GetMapping("/api/v1/orders") public List<Order> ordersV1() { List<Order> all = orderRepository.findAllByString(new OrderSearch()); for (Order order : all) { order.getMember().getName(); order.getDelivery().getAddress(); List<OrderItem> orderItems = order.getOrderItems(); orderItems.forEach(o -> o.getItem().getName()); } return all; }위에 처럼 프록시 초기화(하지만 실제 엔티티의 참조만 가질뿐 객체는 여전히 프록시)를 해주는 이유는 실제 엔티티의 참조를 가지게 하려고 설정하는 것이고,@Bean Hibernate5Module hibernate5Module() { return new Hibernate5Module(); }위에 처럼 Hibernate5Module을 해주는 이유는 프록시 초기화를 해도 객체는 여전히 프록시기 때문에 Json으로 반환할 수 있게 하려는 것이라고 이해했습니다.여기 까지 이해한 부분이 옳게 이해한 것일까요?그리고 마지막으로 @Bean Hibernate5Module hibernate5Module() { Hibernate5Module hibernate5Module = new Hibernate5Module(); // 강제 지연 로딩 설정 hibernate5Module.configure(Hibernate5Module.Feature.FORCE_LAZY_LOADING, true); return new Hibernate5Module(); }위에 처럼 강제 지연 로딩 설정을 왜 쓰는지는 잘 모르겠습니다.강제 지연 로딩 설정이라는 말이 무엇인가요!?혹시 하이버네이트가 @ToOne은 기본이 eager인데 엔티티에서 직접 lazy 설정해준걸 안해도 된다는 소리인가요? 질문이 크게 숫자로 표시한 두가지 입니다! 감사합니다.
-
미해결스프링 핵심 원리 - 기본편
인텔리제이 하단 창이 제대로 안나옵니다.
갑자기 좌측하단창이 나오지 않습니다..어떻게 해야 나오게 할 수 있을까요?
-
미해결스프링부트 시큐리티 & JWT 강의
로그인시 JWT 반환하는거를 구현하려는데 에러
코드 링크 : https://github.com/YuYoHan/JWT나오는 에러 :2023-06-10 13:57:50.618 ERROR 17488 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root causejava.lang.NullPointerException: nullat com.example.jwt.service.UserService.login(UserService.java:61) ~[classes/:na]at com.example.jwt.service.UserService$$FastClassBySpringCGLIB$$41c8b5f9.invoke(<generated>) ~[classes/:na]at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.27.jar:5.3.27]at org.springframework.aop.framework.CglibAopProxy.invokeMethod(CglibAopProxy.java:386) ~[spring-aop-5.3.27.jar:5.3.27]at org.springframework.aop.framework.CglibAopProxy.access$000(CglibAopProxy.java:85) ~[spring-aop-5.3.27.jar:5.3.27]at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:704) ~[spring-aop-5.3.27.jar:5.3.27]at com.example.jwt.service.UserService$$EnhancerBySpringCGLIB$$e9411f63.login(<generated>) ~[classes/:na]at com.example.jwt.controller.UserController.authorize(UserController.java:54) ~[classes/:na]at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[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:566) ~[na:na]at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.27.jar:5.3.27]at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.27.jar:5.3.27]at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.27.jar:5.3.27]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.27.jar:5.3.27]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.27.jar:5.3.27]at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.27.jar:5.3.27]at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1072) ~[spring-webmvc-5.3.27.jar:5.3.27]at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965) ~[spring-webmvc-5.3.27.jar:5.3.27]at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.27.jar:5.3.27]at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.27.jar:5.3.27]at javax.servlet.http.HttpServlet.service(HttpServlet.java:555) ~[tomcat-embed-core-9.0.74.jar:4.0.FR]at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.27.jar:5.3.27]at javax.servlet.http.HttpServlet.service(HttpServlet.java:623) ~[tomcat-embed-core-9.0.74.jar:4.0.FR]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-9.0.74.jar:9.0.74]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:337) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.8.jar:5.7.8]at com.example.jwt.config.jwt.JwtAuthenticationFilter.doFilter(JwtAuthenticationFilter.java:64) ~[classes/:na]at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.27.jar:5.3.27]at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:112) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:82) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.27.jar:5.3.27]at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.27.jar:5.3.27]at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:221) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:186) ~[spring-security-web-5.7.8.jar:5.7.8]at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354) ~[spring-web-5.3.27.jar:5.3.27]at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267) ~[spring-web-5.3.27.jar:5.3.27]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.27.jar:5.3.27]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.27.jar:5.3.27]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.27.jar:5.3.27]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.27.jar:5.3.27]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.27.jar:5.3.27]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.27.jar:5.3.27]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:389) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:926) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1791) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.74.jar:9.0.74]at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na] 제가 알기로는 이 오류는 final을 추가 하지 않아서 생기는 오류로 알고 있는데 문제는 제가 @RequiredArgsConstructor와 final을 모두 추가를 해줬습니다. 그런데 계속 null 오류가 생기네요. 강의와 똑같은 코드는 아니고 변형을 했는데전체 코드는 git 링크를 올렸으니 일단 오류에서 나온 코드만 따로 올립니다.**UserService** import java.util.Optional; @Service @RequiredArgsConstructor public class UserService { private final UserRepository userRepository; private final BCryptPasswordEncoder bCryptPasswordEncoder; private final AuthenticationManagerBuilder authenticationManagerBuilder; private final JwtProvider jwtProvider; @Transactional public UserEntity signUp(User user) throws Exception { UserEntity userEntity = UserEntity.builder() .email(user.getEmail()) .password(bCryptPasswordEncoder.encode(user.getPassword())) .userName(user.getUserName()) .role(Role.USER) .build(); if(userEntity != null) { return userRepository.save(userEntity); } else { throw new Exception("가입이 실패하셨습니다."); } } public Optional<UserEntity> findById(Long userId) { Optional<UserEntity> byId = userRepository.findById(userId); return byId; } public TokenDTO login(String userEmail, String userPw) { UserEntity byEmailAndPassword = userRepository.findByEmailAndPassword(userEmail, userPw); // 1. Login ID/PW를 기반으로 Authentication 객체 생성 // 이 때 authentication는 인증 여부를 확인하는 authenticated 값이 false UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(byEmailAndPassword.getEmail(), byEmailAndPassword.getPassword()); // 2. 실제 검증 (사용자 비밀번호 체크)이 이루어지는 부분 // authenticate 매서드가 실행될 때 CustomUserDetailsService 에서 만든 loadUserByUsername 메서드가 실행 Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken); // 해당 객체를 SecurityContextHolder에 저장하고 SecurityContextHolder.getContext().setAuthentication(authentication); // authentication 객체를 createToken 메소드를 통해서 JWT Token을 생성 // 3. 인증 정보를 기반으로 JWT 토큰 생성 TokenDTO tokenDTO = jwtProvider.createToken(authentication); HttpHeaders headers = new HttpHeaders(); // response header에 jwt token을 넣어줌 headers.add(JwtAuthenticationFilter.HEADER_AUTHORIZATION, "Bearer " + tokenDTO); return tokenDTO; } } **UserController** @PostMapping("/login") public ResponseEntity<?> authorize(@RequestBody User user) { String email = user.getEmail(); String password = user.getPassword(); TokenDTO login = userService.login(email, password); return ResponseEntity.ok().body(login); } @RequiredArgsConstructor @Slf4j public class JwtAuthenticationFilter extends GenericFilterBean { public static final String HEADER_AUTHORIZATION ="Authorization" ; private final JwtProvider jwtProvider; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) request; // 1. Requset Header에서 JWT 토큰 추출 String jwt = resolveToken(httpServletRequest); String requestURI = httpServletRequest.getRequestURI(); if(StringUtils.hasText(jwt) && jwtProvider.validateToken(jwt)) { // 토큰이 유효할 경우 토큰에서 Authentication 객체를 가지고 와서 SecurityContext 에 저장 Authentication authentication = jwtProvider.getAuthentication(jwt); SecurityContextHolder.getContext().setAuthentication(authentication); log.info("Security Context에 '{}' 인증 정보를 저장했습니다., uri : {}", authentication.getName(), requestURI); } else { log.debug("유효한 JWT 토큰이 없습니다. uri : {}", requestURI); } chain.doFilter(request, response); } // Request Header 에서 토큰 정보를 꺼내오기 위한 메소드 private String resolveToken(HttpServletRequest httpServletRequest) { String bearerToken = httpServletRequest.getHeader(HEADER_AUTHORIZATION); if(StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")){ return bearerToken.substring(7); } else { return null; } } } 제가 JWT에 대해서는 잘 몰라서 계획한게 맞는 구성인지는 모르겠지만 계획한 것은JwtProvider에서 accessToken과 refreshToken을 만들고 TokenDTO담아주고 로그인시 그것을 리턴해주려고 계획했습니다. @Slf4j @Component public class JwtProvider { private static final String AUTHORITIES_KEY = "auth"; private Key key; public JwtProvider(@Value("${jwt.secret_key}") String secret ) { byte[] keyBytes = Decoders.BASE64.decode(secret); this.key = Keys.hmacShaKeyFor(keyBytes); } // 유저 정보를 가지고 AccessToken, RefreshToken을 생성하는 메서드 public TokenDTO createToken(Authentication authentication) { // 권한 가져오기 String authorities = authentication.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.joining(",")); long now = (new Date()).getTime(); // Access Token 생성 Date accessTokenExpire = new Date(now + 360000); String accessToken = Jwts.builder() .setSubject(authentication.getName()) .claim("auth", authorities) .setExpiration(accessTokenExpire) .signWith(key, SignatureAlgorithm.ES512) .compact(); // Refresh Token 생성 // Date 생성자에 삽입하는 숫자 86480000은 토큰의 유효기간으로써 1일을 나타낸다. String refreshToken = Jwts.builder() .setExpiration(new Date(now + 86400000)) .signWith(key, SignatureAlgorithm.ES512) .compact(); return TokenDTO.builder() .grantType("Bearer") .accessToken(accessToken) .refreshToken(refreshToken) .build(); } // JWT 토큰을 복호화하여 토큰에 들어있는 정보를 꺼내는 코드 // 토큰으로 클레임을 만들고 이를 이용해 유저 객체를 만들어서 최종적으로 authentication 객체를 리턴 // 인증 정보 조회 public Authentication getAuthentication(String token) { // 토큰 복호화 메소드 Claims claims = parseClaims(token); if(claims.get("auth") == null) { throw new RuntimeException("권한 정보가 없는 토큰입니다."); } // 클레임 권한 정보 가져오기 Collection<? extends GrantedAuthority> authorities = Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(",")) .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); // UserDetails 객체를 만들어서 Authentication 리턴 User principal = new User(claims.getSubject(), "", authorities); return new UsernamePasswordAuthenticationToken(principal, token, authorities); } private Claims parseClaims(String token) { try { return Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token) .getBody(); } catch (ExpiredJwtException e) { return e.getClaims(); } } // 토큰의 유효성 검증을 수행 public boolean validateToken(String token) { try { Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token); return true; } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) { log.info("잘못된 JWT 서명입니다."); } catch (ExpiredJwtException e) { log.info("만료된 JWT 토큰입니다."); } catch (UnsupportedJwtException e) { log.info("지원되지 않는 JWT 토큰입니다."); } catch (IllegalArgumentException e) { log.info("JWT 토큰이 잘못되었습니다."); } return false; } }package com.example.jwt.domain.jwt; import lombok.*; @Getter @Setter @Builder @NoArgsConstructor @AllArgsConstructor public class TokenDTO { // JWT 대한 인증 타입, 여기서는 Bearer를 사용하고 // 이후 HTTP 헤더에 prefix로 붙여주는 타입 private String grantType; private String accessToken; private String refreshToken; } 그리고 추가 질문이 있습니다. PrincipalDetailService에서 @Override public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { UserEntity userEntity = userRepository.findByEmail(email); log.info("user : " + userEntity); return new PrincipalDetails(userEntity); }여기서 오버라이드한게 인자를 username으로 받는데 강의에서는 로그인 자체를 name으로 했지만 저는 로그인을 email형식으로 하려고해서 email로 바꿨는데 맞는건가요..?
-
해결됨토비의 스프링 부트 - 이해와 원리
spring boot 3.0 버전 부터 cli 를 통한 run 명령 사용불가
spring boot 3.0 버전 부터 CLI 를 통한 run 명령어가 사용불가능한 것으로 보이는데 대체할 수 있는 방법이 있을까요?https://github.com/spring-projects/spring-boot/issues/32263
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
1+n 문제 관련 궁금증 입니다.
1+n문제에서 n이 1에서 조회한 갯수 라고 하셨는데요.order 2개를 찾았을 때 member와 delivery를 불러와야 하므로 1 + 2*2 인 것 같습니다.만약 멤버와 딜리버리 말고 찾아야하는 지연 로딩 속성이 10개 라면 1+2*10 이니까 사실은 1+N이 자세히 보면 1+N*M 문제 라고 혼자 나름대로 이해를 해도 괜찮을까요?M은 상수라서 생략하는 거 같은데 혹시 맞을까요?
-
미해결스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술
DB관련
마리아 디비로 해도 상관없는거죠?
-
미해결토비의 스프링 부트 - 이해와 원리
intellij 기본 터미널을 warp 로 변경 방법 알려주셔요.
안녕하세요.제목대로 intellij 터미널이 현재는 zsh 로 되어 있는데 외부 어플인 warp 로 변경하는 방법 좀 알려주시면 감사하겠습니다.꾸우벅~~
-
해결됨스프링 핵심 원리 - 기본편
객체 생성에 대해 질문드립니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)네2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)아니요3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)네[질문 내용]저와 같은 생각을 하신분이 질문을 했는데제가 이해한게 맞는지 여쭤봅니다.ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); 이게 아닌 AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);으로 강의에서 말씀하셨는데개방 폐쇄 원칙에는 ApplicationContext 를 사용하는게 맞지만AnnotationConfigApplicationContext 에서 필요한 기능이 있기때문에 AnnotationConfigApplicationContext 이걸로 사용했다고 보면 될까요? 개방 폐쇄 원칙에는 어긋나지만 테스트기때문에 사용했다 라고 보면 될까요?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
데이타소스없이 JpaRepository 작동하는 이유
안녕하세요.문득 스프링 데이타 JPA로 테스트 진행 중 없는 테이블을 만들어주는 기능을 보니 db에 커넥션이 없이 이 모든 게 진행된다는 게 갑자기 낯선 느낌이 들었습니다.쿼리를 만들고 날리는 과정이 커넥션 여부와 관계없이 실행되는 것인가요? 어떻게 데이타소스 없이 작동하는건지 조금 이상하다는 생각이 듭니다.트랜잭션과 관련있는 내용은 아니지만 강의에서 설명을 들으니 문득 궁금해져 질문 드립니다.감사합니다.
-
미해결실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화
default_batch_fetch_size 설정을 지워도 지연로딩이 적용되지 않습니다.
default_batch_fetch_size 설정을 주었을때 쿼리가 나가는것과 default_batch_fetch_size 설정을 주석처리 했을때 쿼리 나가는것을 비교해보고 싶어서 테스트 코드를 아래와 같이 작성해봤습니다.@Test @DisplayName("회원 불러와서 getFriends 할때, default_batch_fetch_size 설정 여부에 따른 쿼리 개수 확인") public void findOne() throws Exception { //given Member member = Member.builder() .name("userA") .build(); Friend friendA = Friend.builder() .name("friendA") .member(member) .build(); Friend friendB = Friend.builder() .name("friendB") .member(member) .build(); Friend friendC = Friend.builder() .name("friendC") .member(member) .build(); Friend friendD = Friend.builder() .name("friendD") .member(member) .build(); Friend friendE = Friend.builder() .name("friendE") .member(member) .build(); //when memberRepository.save(member); friendRepository.save(friendA); friendRepository.save(friendB); friendRepository.save(friendC); friendRepository.save(friendD); friendRepository.save(friendE); em.flush(); em.clear(); //then Member findMember = memberRepository.findById(member.getId()); List<Friend> friends = findMember.getFriends(); for (Friend friend : friends) { log.info("getClass: " + friend.getClass()); // 프록시객체를 기대.. log.info("getClass: " + friend.getName()); } }Member와 Friend는 일대다 관계이며,Member 클래스에 있는 연관관계 필드는 다음과 같고,@OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) private final List<Friend> friends = new ArrayList<>();Friend 클래스에 있는 연관관계 필드는 다음과 같습니다.@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="member_id") private Member member;테스트코드에서,,Member findMember = memberRepository.findById(member.getId()); 이 부분에서 member를 조회하는 쿼리가 한번,log.info("getClass: " + friend.getClass()); 이 부분에서 프록시객체가 찍히고,log.info("getClass: " + friend.getName()); 이 부분에서 원본 객체를 조회하기 위해 쿼리가 한번 나가서, for문을 돌면서 총 1 + 5 개의 쿼리가 나가기를 기대했습니다.그리고 default_batch_fetch_size:100 를 글로벌설정에 주게 되면 멤버 조회하는 쿼리 1번, 해당 멤버와 관련된 전체 friend 들을 다 조회하는 쿼리 1번이 나가고 더이상 안나가게 되지 않을까 기대했습니다.그런데, 글로벌설정을 주기도 전에 1+5개의 조회 쿼리가 나가지가 않고 2개의 조회쿼리만 나가고 끝이 나네요..default_batch_fetch_size:100 이 옵션을 주석처리도 해보고, 아예 지워도 보고 default_batch_fetch_size:1 로도 값을 변경해보기도 하였지만 결과는 같았습니다.로그는 다음과 같습니다.2023-06-09 21:35:26.695 INFO 1106 --- [ Test worker] o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext@1bdaa23d testClass = MemberRepositoryTest, testInstance = com.example.myvers.member.MemberRepositoryTest@7ae75ba6, testMethod = findOne@MemberRepositoryTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@79f227a9 testClass = MemberRepositoryTest, locations = '{}', classes = '{class com.example.myvers.MyversApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@42f48531, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@ea9b7c6, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@a8e6492, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@60dce7ea, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@f73dcd6, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@43015c69], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@7b6b466a]; rollback [true] 2023-06-09 21:35:26.749 DEBUG 1106 --- [ Test worker] org.hibernate.SQL : call next value for hibernate_sequence 2023-06-09 21:35:26.749 INFO 1106 --- [ Test worker] p6spy : #1686314126749 | took 0ms | statement | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b call next value for hibernate_sequence call next value for hibernate_sequence; 2023-06-09 21:35:26.750 DEBUG 1106 --- [ Test worker] org.hibernate.SQL : call next value for hibernate_sequence 2023-06-09 21:35:26.750 INFO 1106 --- [ Test worker] p6spy : #1686314126750 | took 0ms | statement | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b call next value for hibernate_sequence call next value for hibernate_sequence; 2023-06-09 21:35:26.750 DEBUG 1106 --- [ Test worker] org.hibernate.SQL : call next value for hibernate_sequence 2023-06-09 21:35:26.750 INFO 1106 --- [ Test worker] p6spy : #1686314126750 | took 0ms | statement | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b call next value for hibernate_sequence call next value for hibernate_sequence; 2023-06-09 21:35:26.750 DEBUG 1106 --- [ Test worker] org.hibernate.SQL : call next value for hibernate_sequence 2023-06-09 21:35:26.750 INFO 1106 --- [ Test worker] p6spy : #1686314126750 | took 0ms | statement | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b call next value for hibernate_sequence call next value for hibernate_sequence; 2023-06-09 21:35:26.750 DEBUG 1106 --- [ Test worker] org.hibernate.SQL : call next value for hibernate_sequence 2023-06-09 21:35:26.750 INFO 1106 --- [ Test worker] p6spy : #1686314126750 | took 0ms | statement | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b call next value for hibernate_sequence call next value for hibernate_sequence; 2023-06-09 21:35:26.750 DEBUG 1106 --- [ Test worker] org.hibernate.SQL : call next value for hibernate_sequence 2023-06-09 21:35:26.750 INFO 1106 --- [ Test worker] p6spy : #1686314126750 | took 0ms | statement | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b call next value for hibernate_sequence call next value for hibernate_sequence; 2023-06-09 21:35:26.751 DEBUG 1106 --- [ Test worker] org.hibernate.SQL : insert into member (created_date, email, grade, login_id, name, password, talk_count, member_id) values (?, ?, ?, ?, ?, ?, ?, ?) 2023-06-09 21:35:26.752 INFO 1106 --- [ Test worker] p6spy : #1686314126752 | took 0ms | statement | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b insert into member (created_date, email, grade, login_id, name, password, talk_count, member_id) values (?, ?, ?, ?, ?, ?, ?, ?) insert into member (created_date, email, grade, login_id, name, password, talk_count, member_id) values (NULL, NULL, NULL, NULL, 'userA', NULL, 1, 33); 2023-06-09 21:35:26.752 DEBUG 1106 --- [ Test worker] org.hibernate.SQL : insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (?, ?, ?, ?, ?, ?, ?, ?) 2023-06-09 21:35:26.752 INFO 1106 --- [ Test worker] p6spy : #1686314126752 | took 0ms | statement | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (?, ?, ?, ?, ?, ?, ?, ?) insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (0, NULL, NULL, NULL, NULL, 33, 'friendA', 34); 2023-06-09 21:35:26.752 DEBUG 1106 --- [ Test worker] org.hibernate.SQL : insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (?, ?, ?, ?, ?, ?, ?, ?) 2023-06-09 21:35:26.752 INFO 1106 --- [ Test worker] p6spy : #1686314126752 | took 0ms | statement | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (?, ?, ?, ?, ?, ?, ?, ?) insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (0, NULL, NULL, NULL, NULL, 33, 'friendB', 35); 2023-06-09 21:35:26.753 DEBUG 1106 --- [ Test worker] org.hibernate.SQL : insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (?, ?, ?, ?, ?, ?, ?, ?) 2023-06-09 21:35:26.753 INFO 1106 --- [ Test worker] p6spy : #1686314126753 | took 0ms | statement | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (?, ?, ?, ?, ?, ?, ?, ?) insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (0, NULL, NULL, NULL, NULL, 33, 'friendC', 36); 2023-06-09 21:35:26.753 DEBUG 1106 --- [ Test worker] org.hibernate.SQL : insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (?, ?, ?, ?, ?, ?, ?, ?) 2023-06-09 21:35:26.753 INFO 1106 --- [ Test worker] p6spy : #1686314126753 | took 0ms | statement | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (?, ?, ?, ?, ?, ?, ?, ?) insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (0, NULL, NULL, NULL, NULL, 33, 'friendD', 37); 2023-06-09 21:35:26.753 DEBUG 1106 --- [ Test worker] org.hibernate.SQL : insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (?, ?, ?, ?, ?, ?, ?, ?) 2023-06-09 21:35:26.753 INFO 1106 --- [ Test worker] p6spy : #1686314126753 | took 0ms | statement | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (?, ?, ?, ?, ?, ?, ?, ?) insert into friend (age, created_date, gender, image_name, mbti, member_id, name, friend_id) values (0, NULL, NULL, NULL, NULL, 33, 'friendE', 38); 2023-06-09 21:35:26.759 DEBUG 1106 --- [ Test worker] org.hibernate.SQL : select member0_.member_id as member_i1_1_0_, member0_.created_date as created_2_1_0_, member0_.email as email3_1_0_, member0_.grade as grade4_1_0_, member0_.login_id as login_id5_1_0_, member0_.name as name6_1_0_, member0_.password as password7_1_0_, member0_.talk_count as talk_cou8_1_0_ from member member0_ where member0_.member_id=? 2023-06-09 21:35:26.760 INFO 1106 --- [ Test worker] p6spy : #1686314126760 | took 0ms | statement | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b select member0_.member_id as member_i1_1_0_, member0_.created_date as created_2_1_0_, member0_.email as email3_1_0_, member0_.grade as grade4_1_0_, member0_.login_id as login_id5_1_0_, member0_.name as name6_1_0_, member0_.password as password7_1_0_, member0_.talk_count as talk_cou8_1_0_ from member member0_ where member0_.member_id=? select member0_.member_id as member_i1_1_0_, member0_.created_date as created_2_1_0_, member0_.email as email3_1_0_, member0_.grade as grade4_1_0_, member0_.login_id as login_id5_1_0_, member0_.name as name6_1_0_, member0_.password as password7_1_0_, member0_.talk_count as talk_cou8_1_0_ from member member0_ where member0_.member_id=33; 2023-06-09 21:35:26.765 DEBUG 1106 --- [ Test worker] org.hibernate.SQL : select friends0_.member_id as member_i8_0_0_, friends0_.friend_id as friend_i1_0_0_, friends0_.friend_id as friend_i1_0_1_, friends0_.age as age2_0_1_, friends0_.created_date as created_3_0_1_, friends0_.gender as gender4_0_1_, friends0_.image_name as image_na5_0_1_, friends0_.mbti as mbti6_0_1_, friends0_.member_id as member_i8_0_1_, friends0_.name as name7_0_1_ from friend friends0_ where friends0_.member_id=? 2023-06-09 21:35:26.766 INFO 1106 --- [ Test worker] p6spy : #1686314126766 | took 0ms | statement | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b select friends0_.member_id as member_i8_0_0_, friends0_.friend_id as friend_i1_0_0_, friends0_.friend_id as friend_i1_0_1_, friends0_.age as age2_0_1_, friends0_.created_date as created_3_0_1_, friends0_.gender as gender4_0_1_, friends0_.image_name as image_na5_0_1_, friends0_.mbti as mbti6_0_1_, friends0_.member_id as member_i8_0_1_, friends0_.name as name7_0_1_ from friend friends0_ where friends0_.member_id=? select friends0_.member_id as member_i8_0_0_, friends0_.friend_id as friend_i1_0_0_, friends0_.friend_id as friend_i1_0_1_, friends0_.age as age2_0_1_, friends0_.created_date as created_3_0_1_, friends0_.gender as gender4_0_1_, friends0_.image_name as image_na5_0_1_, friends0_.mbti as mbti6_0_1_, friends0_.member_id as member_i8_0_1_, friends0_.name as name7_0_1_ from friend friends0_ where friends0_.member_id=33; 2023-06-09 21:35:26.768 INFO 1106 --- [ Test worker] c.e.myvers.member.MemberRepositoryTest : getClass: class com.example.myvers.domain.Friend 2023-06-09 21:35:26.768 INFO 1106 --- [ Test worker] c.e.myvers.member.MemberRepositoryTest : getClass: friendA 2023-06-09 21:35:26.768 INFO 1106 --- [ Test worker] c.e.myvers.member.MemberRepositoryTest : getClass: class com.example.myvers.domain.Friend 2023-06-09 21:35:26.768 INFO 1106 --- [ Test worker] c.e.myvers.member.MemberRepositoryTest : getClass: friendB 2023-06-09 21:35:26.768 INFO 1106 --- [ Test worker] c.e.myvers.member.MemberRepositoryTest : getClass: class com.example.myvers.domain.Friend 2023-06-09 21:35:26.768 INFO 1106 --- [ Test worker] c.e.myvers.member.MemberRepositoryTest : getClass: friendC 2023-06-09 21:35:26.768 INFO 1106 --- [ Test worker] c.e.myvers.member.MemberRepositoryTest : getClass: class com.example.myvers.domain.Friend 2023-06-09 21:35:26.768 INFO 1106 --- [ Test worker] c.e.myvers.member.MemberRepositoryTest : getClass: friendD 2023-06-09 21:35:26.768 INFO 1106 --- [ Test worker] c.e.myvers.member.MemberRepositoryTest : getClass: class com.example.myvers.domain.Friend 2023-06-09 21:35:26.768 INFO 1106 --- [ Test worker] c.e.myvers.member.MemberRepositoryTest : getClass: friendE 2023-06-09 21:35:26.771 INFO 1106 --- [ Test worker] p6spy : #1686314126771 | took 0ms | rollback | connection 16| url jdbc:h2:mem:bd08892f-1de8-4235-819c-08b14b2b1f5b ; 2023-06-09 21:35:26.772 INFO 1106 --- [ Test worker] o.s.t.c.transaction.TransactionContext : Rolled back transaction for test: [DefaultTestContext@1bdaa23d testClass = MemberRepositoryTest, testInstance = com.example.myvers.member.MemberRepositoryTest@7ae75ba6, testMethod = findOne@MemberRepositoryTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@79f227a9 testClass = MemberRepositoryTest, locations = '{}', classes = '{class com.example.myvers.MyversApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@42f48531, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@ea9b7c6, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@a8e6492, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@60dce7ea, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@f73dcd6, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@43015c69], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.populatedRequestContextHolder' -> true, 'org.springframework.test.context.web.ServletTestExecutionListener.resetRequestContextHolder' -> true, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]] 결론: default_batch_fetch_size 설정을 지워도 지연로딩이 적용되지 않는 이유를 알고싶습니다. 감사합니다.
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
테스트에서 @Slf4j 를 따로 선언하는 이유가 궁금합니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 테스트 클래스에 @Slf4j를 붙이고 그 아래 static 클래스에도 붙이셔서 그 이유가 궁금합니다.테스트 클래스에만 선언하면 되지않나? 라는 생각이 들어서 static 클래스에 있는 @Slf4j를 지워 보고 했는데 로그는 잘 나오더라구요.혼자 찾아보려 했는데 잘 안돼서 질문남깁니다 ㅠ