[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 여기에 질문 내용을 남겨주세요. 강의내용대로 @Transactional 넣고 스프링부트띄워서 테스트를 돌리면 rollback이 바로되는게 아니라 좀 지나서 되는것 같더라구요 회원가입 테스트 돌리고 디비에서 member조회 해보면 인서트가 되어있고 한번더 조회하면 그때 사라지더라구요 그것 때문에 회원가입과 중복회원 따로 돌리면 되긴하는데 전체 테스트를 돌리면 중복회원예외에서 실패가 납니다. 어떻게 해야될까요..?
안녕하세요 강의 잘 듣고 있습니다. 중간에 조회 API 개발의 내용 중 QMemberTeamDto를 조회하는 메소드로 컨트롤러를 통해 응답을 주는 컨트롤러를 작성하는 내용이 있는데요 같은 내용의 Test는 통과하였으나 포스트맨에서 요청을 할 때는 NoClassDefFound 에러가 발생합니다 build가 되지 않았나? 해서 gradle로 clean compileJava compileQuerydsl 모두 실행하고 해봐도 같은 결과입니다 빌드된 결과 에러 내용
안녕하세요 선생님 JPA Repository에서 save메서드 호출 이후 바로 user id를 가지고 올 수 있는 이유가 너무 궁금하여 질문글을 올렸습니다. User entity를 생성한 후 아래와 같이 테스트를 진행해 보았습니다. 아래는 저의 테스트코드입니다. user 객체를 생성, user 객체에서 id 확인 db에 들어가기 전이기 때문에 id가 당연히 없을 것으로 예상 user 객체를 저장 user 객체에서 id 확인, db에서 다시 조회를 하지 않았기 때문에 id가 없을 것으로 예상하였지만 id가 존재 아래와 같은 결과를 얻을 수 있었습니다. JPARepository의 save method는 아래와 같았습니다. 1. save를 했을 때 바로 insert query 발생하는 이유 -> save 메서드를 살펴보면 @Transactional annotation이 존재하고, save 메서드 종료시 em.flush 발생으로 인해 바로 query가 발생하는 것으로 생각함. 2. user.getId를 받아올 수 있는 이유는 뭘까 user.getId를 받아올 수 있는 경우는 db에 저장을 완료하고, db에 있는 user 정보를 다시 조회했을 때 받아올 것이라고 생각한 것과 달리, save 메서드를 실행하자마자 db 저장 내용이 바로 반영이 된 것을 확인할 수 있었습니다. 따로 select query문이 발생하지 않은 것으로 보아, db 조회는 없었다는 것을 알 수 있습니다. persistcontext와 dirty check에 의해서 이러한 현상이 발생한 것이라고 추측은 하고 있습니다만 이게 어떻게 가능한 일인지 궁금합니다. 제 User entity는 아래와 같습니다. id의 생성시점은 user entity를 db에 저장하는 시점에 생성되는 것이라고 생각하는데, (쓰기 지연 SQL 저장소에서 flush 이후에 id값이 생성될 것이라고 생각함) 생성 이후에는 db에서 user를 다시 가져오고 있지 않습니다. 변경감지로 user id가 생성된 것인지, JPA repositoy에서 save 메서드 이후에 entity를 return 해 주기 때문인지 궁금합니다. 3. EntityManager의 생명주기는 Transactional의 생명주기와 동일하며, PersistContext의 생명주기는 EntityManagerFactory의 생명주기와 동일하게 Application loading 시점과 WAS가 종료되는 시점에 생성과 사멸을 한다고 볼 수 있는 것일까요? 4. 위와 동일한 맥락으로 저의 테스트 코드에서의 영속성 컨텍스트와 JPA Repository의 save 메서드 내의 영속성 컨텍스트는 동일한 영속성 컨텍스트라고 보면 될까요?
안녕하세요 영한님. 올려주신 spring 강의부터 jpa까지 거의 다 듣고 배운것을 활용해서 토이 프로젝트 만들고 있습니다. web api 설계시에 궁금한것이 있어 문의드립니다. 만약 parents 있고 children이 존재합니다. parent와 children은 1대N 관계입니다. 제가 처음 백엔드 api 설계했을때 아래처럼 설계했습니다. POST /parents : parents 리소스가 생성됩니다. POST /parents/{id}/children : parent와 연관된 children 이 생성됩니다. 설계를 마치고 프론트엔드에서 해당 api를 이용해서 등록하려했습니다. 여기서 궁금한것이 생겼습니다. 아래 두 방식중 어떤것이 좋은것인지 잘모르겠습니다. 1. 프론트에서 한번의 Post 요청으로 parents와 childrens list를 모두 생성합니다. request body 예시: { parent: "..." children:[ "...", "..." ] } 백엔드에서 parent정보로 parent 리소스를 만들고 만들어진 parent의 id와 body에 있는 children 리스트로 children 리소스를 생성합니다. 2. 프론트에서 POST /parent와 POST /parent/{id}/children을 각각 요청합니다. 먼저 POST /parents 요청을 보내고 응답값에서 parents id를 받아 children 갯수만큼 POST /parents/{id}/childrens 요청을 합니다.(이럴경우 요청수는 1+N이 겠네요). 1번과 2번 방식중에 어떤 방법이 나은지 잘 모르겠습니다. 제가 생각한 각각의 장단점입니다. 1번의 장점 : 하나의 요청에 모든 정보가 들어있어 요청 처리중 에러 발생시 기존에 저장된 정보도 롤백이 가능하다는 장점이 있을것같습니다. 또한 request도 한번이면 됩니다. 1번의 단점 : api가 직관적이지 않은것같습니다. 클라이언트는 POST /parents를 사용하면 parents 리소스가 생길것으로 예상합니다. 하지만 해당 요청으로 children이 생길것이라는것은 문서를 봐야합니다. 또한 유연하지 않다고 생각합니다(클라이언트마다 구현방식이 다를것이므로) 2번의 장점 : api가 직관적입니다. 유연합니다. 클라이언트가 구현방식을 바꾸더라도 백엔드의 api를 바꾸지 않아도 될것같습니다. 2번의 단점 : 클라이언트쪽에서 여러번 api를 호출해야합니다. 요청 도중에 에러가 발생할 경우 parents는 등록되고 children은 등록이 안될수도 있습니다. 둘중에 어떤것 방식을 실무에서 사용하나요? 2번으로 마음이 좀 기울긴하는데, 위에 적히 단점들이 걸리네요.. 그리고 클라이언트쪽에서 N개의 children를 모두 등록하고 싶을때 body에 list를 담아서 post /children 전부를 한번에 보내서 처리할수있게 api를 만드는게 좋은것인가요? (하나의 요청으로 여러개의 리소스 생성, 백엔드에서 리스트를 순회하면서 저장) 아니면 클라이언트쪽에서 list를 순회하면서 N번 post 요청 하게 만드는것이 좋은가요?( 하나의 요청으로 하나의 리소스생성, 대신 여러번 호출) 긴글 읽어주셔서 감사합니다.
왜 에러가 나오는지 모르겠습니다. Controller에서 Mapping 할 때 그냥 hello로 하면 404가 나오고 /hello 로 하게 되면 500 에러가 나오게 됩니다. 022-05-04 12:15:15.062 ERROR 5008 --- [nio-8080-exec-9] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: Error resolving template [hello!], template might not exist or might not be accessible by any of the configured Template Resolvers] with root cause org.thymeleaf.exceptions.TemplateInputException: Error resolving template [hello!], template might not exist or might not be accessible by any of the configured Template Resolvers at org.thymeleaf.engine.TemplateManager.resolveTemplate(TemplateManager.java:869) ~[thymeleaf-3.0.15.RELEASE.jar:3.0.15.RELEASE] at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:607) ~[thymeleaf-3.0.15.RELEASE.jar:3.0.15.RELEASE] at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098) ~[thymeleaf-3.0.15.RELEASE.jar:3.0.15.RELEASE] at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072) ~[thymeleaf-3.0.15.RELEASE.jar:3.0.15.RELEASE] at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:366) ~[thymeleaf-spring5-3.0.15.RELEASE.jar:3.0.15.RELEASE] at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:190) ~[thymeleaf-spring5-3.0.15.RELEASE.jar:3.0.15.RELEASE] at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1401) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1145) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1084) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.19.jar:5.3.19] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.19.jar:5.3.19] at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.62.jar:4.0.FR] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.19.jar:5.3.19] at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.62.jar:4.0.FR] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.19.jar:5.3.19] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.19.jar:5.3.19] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.19.jar:5.3.19] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.19.jar:5.3.19] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.19.jar:5.3.19] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.19.jar:5.3.19] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.62.jar:9.0.62] at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
실무에서 DB 를 사용한다고 하면 배치나 데이터 파이프라인 등이 아닌 OLTP 환경에서는 절대 오프셋 기반의 페이징을 쓰면 안되지 않나요? 우선 페이징 도중에 다른 클라이언트에 의해 실시간으로 데이터가 삽입/삭제가 일어나 중복된 데이터가 보여지거나 중간 데이터 누락이 발생할 수도 있기 때문에 문제가 될 것이고, 성능의 관점에서도 SQL 쿼리에서 OFFSET 문의 경우 index seek 과정에서 바로 페이지의 첫 데이터를 찾아가는것이 아니라 불필요하게 맨 처음 인덱스부터 offset 사이즈만큼 스캔한 뒤에 limit 만큼 가져오는 것이기 때문에 scalable 않지만, 커서 기반의 페이징의 경우 데이터의 양이 많아지더라도 where 절을 통해 index seek 과정에서 바로 커서에 해당하는 인덱스를 찾아가서 page size 만큼의 데이터만 스캔하면 되기 때문에 실무에서 굳이 오프셋 기반의 페이징을 쓸 이유가 없다. 라고 이해하면 맞을까요? 물론 페이징 대상이 되는 데이터의 수 자체가 매우 적거나 유저가 많은 페이지를 탐색하지 않는다면 큰 문제가 되지 않을 수도 있지만, 커서 기반의 페이징을 구현하는것이 특별이 어려운 것도 아니고 굳이 오프셋 기반의 페이징을 사용할 필요가 있나 궁금했습니다!
안녕하세요 강의 잘 듣고 있습니다. 다름이 아니라, 본 강의에선 DefaultTourBuilder 구현체로 빌더 패턴 사용 예시를 보여주셨습니다. 1. 첫 번째 질문으로, 칸쿤 여행의 경우 TourPlan의 모든 멤버 변수에 어떤 값을 할당해야 한다고 가정했을 때, 강의에선 getPlan에서 모든 변수가 제대로 초기화됐는지 체크하는 과정이 생략된 것 같은데 맞을까요? 2. DefaultTourBuilder가 칸쿤 여행과 같이 모든 멤버 변수를 초기화했을 때만 인스턴스를 만들 수 있도록 getPlan에 제약을 걸어놨다면, 본 강의에서 예시로 들었던 당일치기 롱비치 여행은 DefaultTourBuilder로 만들 수 없다고 생각합니다. 여러 방법이 존재하겠지만 강의에서 말씀하신 내용을 되짚어보면 당일치기 여행 인스턴스를 제공하는 ShortTourBuilder를 만드는 게 합리적이란 생각이 듭니다. 강사님의 의견은 어떠신가요? 감사합니다.
안녕하세요 . 강의 너무나 잘 듣고 있어 언제나 감사드립니다 . (_ _) DTO 관련해서 궁금점이 있어 질문드립니다. 제가 많이 본 , 그리고 제가 지금도 쓰고있는 폴더 트리 ( 패키지 구조 ) 가 아래와 같이 사용하고 있습니다 . - Model - | Repository - | Service - | Controller ▼ Service단의 경우에는 다른 서비스단에서 연계해서 사용될 수도 있다고 들은적이 있어서, 최대한 Model 클래스를 반환되도록 사용하고 있구요. 위와 연계해서 Controller단에서 Model 클래스를 DTO로 변환해서 반환을 했습니다. 그래서 DTO의 위치가 Controller 패키지에 위치시키고 있었습니다. 그런데 join 쿼리로 인해서 DTO 를 Repository 에서 반환하게 된다면 , 해당 DTO 의 위치가 맨 끝인 Controller 패키지에 있어도 되는 걸까요 ?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 페치조인의 한계로, 일대다 관계에서 컬렉션을 함께 조회하는 페치조인의 경우 데이터 뻥튀기 문제가 일어나기 떄문에, 둘 이상의 컬렉션을 페치조인으로 함께 가져오려고 하면 더더욱 안된다고 설명해주셨습니다. 그렇다면 Order - (1:N) - Order_Item - (N:1) - Item 의 경우 Order_Item을 조회할 때 Order와 Item을 모두 함께 가져오는 페치조인은 해도 되는것인지 궁금합니다. (즉 둘 이상의 컬렉션을 가져오는게 아닌, 둘 이상의 Entity를 가져오는 페치조인의 경우는 써도 되는지) ( select o from OrderItem o join fetch o.orders join fetch o.item 과 같은 JPQL을 사용하여 )
안녕하세요! 실무에서 jpa를 쓰게 되서 강사님의 책과 강의를 번갈아 보면서 열심히 개발하던 중에 궁금한 점이 있어 문의드립니다. 쓰다보니 query dsl이 참 편하더라구요! 그런데 연관관계 없는 두 개 entity를 조인해서 데이터를 조회해오고 싶은데, 아래와 같이 쿼리를 작성하니 실행 중에 QuerySyntaxException이 발생합니다. List < HistoryDto > historyList = queryFactory .select ( Projections. fields ( HistoryDto. class, pmntHistoryEntity. approvalNo , pmntHistoryEntity. approvalDate , pmntHistoryEntity. cancelType , pmntHistoryEntity. trxId , pmntHistoryEntity. trxReqDate , creditCardEntity.cardName , creditCardEntity.cardNumber )) .from ( pmntHistoryEntity) .leftJoin ( creditCardEntity) .on ( pmntHistoryEntity. cardToken .eq ( creditCardEntity.cardToken )) .where ( eqUserId ( dto.getUserId ()) , eqOrderId ( dto.getOrderId ()) ) .fetch () ; exception = QuerySyntaxException: begin 0, end -1, length 19 queryDsl에서 연관 관계 없어도 on 절을 통해 join이 가능한 것으로 알고 있는데 projection과 호환이 안되는 걸까요? 하루종일 구글링을 해도 나오질 않네요.. 혹시 알고 계시다면 답변 부탁드립니다 ㅠ_ㅠ
@GetMapping("/api/v2/orders") public List<OrderDto> ordersV2() { List<Order> orders = orderRepository.findAllByString(new OrderSearch()); List<OrderDto> result = orders.stream() .map( o -> new OrderDto(o) ) .collect(Collectors.toList()); return result; } @Data static class OrderDto { private Long orderId; private String name; private LocalDateTime orderDate; private OrderStatus orderStatus; private Address address; private List<OrderItem> orderItems; public OrderDto(Order order) { orderId = order.getId(); name = order.getMember().getName(); orderDate = order.getOrderDate(); orderStatus = order.getStatus(); address = order.getDelivery().getAddress(); order.getOrderItems().stream().forEach(o -> o.getItem().getId()); orderItems = order.getOrderItems(); } } 위 코드에서 OrderDto 생성자 함수 내에 getOrderItem 요소들을 순회시, 각 아이템을 get후에 getId를 호출 할 때 각 item 프록시들이 초기화 돼야 하는 것 아닌가요..? 강의에서는 getName을 통해 초기화 하길래, 위 코드처럼 getId로 하면 될까 궁금증이 생겨 실행해보니 orderItems 내에 item 이 null 값으로 나옵니다. getName 으로 초기화 할 때는 전부 다 들어있구요. 코드 구글 드라이브 링크: https://drive.google.com/drive/folders/17gdIodVzIPG8_XzTeYUVDbLdaScP6c2s
Flyweight Pattern 이론 강의 자료 중에 내적인 요소, 외적인 요소의 영어 표현으로 [Intrinsit], [extrinsit] 라는 표현이 있는데 해당 표현들은 [Intrinsic], [extrinsic] 표현인거 같습니다. 혹시 오타이신건가요? 항상 좋은 강의 감사드립니다.
안녕하세요 강의 잘 보고 있습니다. 다름이 아니라 제가 Spring Security로 예제를 만들어보고 있었습니다. 그런데 익명 사용자인 경우 컨트롤러의 Authentication 파라미터로 주입되지 않더라고요. @GetMapping("/authentication") @ResponseBody public String authenticationTest(Authentication authentication) 예를 들면 컨트롤러에 이런 함수를 만들면 일반적인 인증 사용자인 경우에는 Authentication 객체가 주입되지만 익명 사용자인 경우에는 Authentication객체가 주입되지 않았습니다. 이유를 찾아보니 표준 서블릿 API 스펙을 따르기 위해서라고 합니다. 다른 응용 프로그램이 spring security의 구현에 의지하지 않도록 하기 위해서고 굳이 익명 사용자인 경우에도Authentication 객체를 주입받고 싶으면 spring security의 getContext().getAuthentication() api를 사용하면 된다고 합니다. 그래서 이유에 대해서는 제가 이렇게 찾아서 궁금한 부분은 아닌데요. https://github.com/spring-projects/spring-security/issues/4011 이 링크에 가보시면 내부적으로 왜 Authentication 객체가 익명 사용자인 경우 컨트롤러에 주입이 안 되는지 나온 부분이 있습니다. SecurityContextHolderAwareRequestWrapper이 객체에 아래와 같은 부분이 있다는 것입니다. private Authentication getAuthentication() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (!trustResolver.isAnonymous(auth)) { return auth; } return null; } SecurityContextHolderAwareRequestWrapper 객체는 HttpServletRequest가 RequestCacheAwareFilter를 통과하면서 재구성된 request 객체라고 합니다. 그래서 SecurityContextHolderAwareRequestWrapper객체에서 getAuthentication()라는 함수를 호출해서 Controller의 Authentication 타입 파라미터에 주입해주는 Security전용 HandlerMethodArgumentResolver가 있을 것 같은데, 제가 아무리 찾아봐도 정확히 이런 Resolver가 있다는 글을 못 찾겠더라고요. 혹시 아신다면 알려주시면 감사하겠습니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] h2데이터베이스 서버모드로 해두었고 서버에 접속도 잘됍니다. java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132) at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124) at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:190) at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:132) 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:197) at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:310) 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:762) 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:364) 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:1511) 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:1511) 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:71) 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:235) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54) Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration': Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.boot.context.properties.ConfigurationPropertiesBindException: Error creating bean with name 'spring.jpa-org.springframework.boot.autoconfigure.orm.jpa.JpaProperties': Could not bind properties to 'JpaProperties' : prefix=spring.jpa, ignoreInvalidFields=false, ignoreUnknownFields=true; nested exception is org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'spring.jpa.show-sql' to boolean at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) 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.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:410) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) 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.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1154) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:908) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:144) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) ... 71 more Caused by: org.springframework.boot.context.properties.ConfigurationPropertiesBindException: Error creating bean with name 'spring.jpa-org.springframework.boot.autoconfigure.orm.jpa.JpaProperties': Could not bind properties to 'JpaProperties' : prefix=spring.jpa, ignoreInvalidFields=false, ignoreUnknownFields=true; nested exception is org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'spring.jpa.show-sql' to boolean at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:92) at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:78) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:440) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) 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.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1389) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1309) at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ... 98 more Caused by: org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'spring.jpa.show-sql' to boolean at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:384) at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:344) at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:469) at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:95) at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:83) at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:59) at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:473) at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:587) at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:573) at org.springframework.boot.context.properties.bind.Binder$Context.access$300(Binder.java:534) at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:471) at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:411) at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:340) at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:329) at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:259) at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:246) at org.springframework.boot.context.properties.ConfigurationPropertiesBinder.bind(ConfigurationPropertiesBinder.java:95) at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:89) ... 112 more Caused by: org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [boolean] for value 'ture'; nested exception is java.lang.IllegalArgumentException: Invalid boolean value 'ture' at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47) at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192) at org.springframework.boot.context.properties.bind.BindConverter.convert(BindConverter.java:109) 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:456) at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:400) at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:340) ... 128 more Caused by: java.lang.IllegalArgumentException: Invalid boolean value 'ture' at org.springframework.core.convert.support.StringToBooleanConverter.convert(StringToBooleanConverter.java:66) at org.springframework.core.convert.support.StringToBooleanConverter.convert(StringToBooleanConverter.java:32) at org.springframework.core.convert.support.GenericConversionService$ConverterAdapter.convert(GenericConversionService.java:386) at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41) ... 135 more 위와 같이 에러가 뜨는데 인프런 홈페이지에 같은 오류코드 질문이 있어 확인해봤습니다. JPA와 DB설정, 동작확인 과정 에러 - 인프런 | 질문 & 답변 (inflearn.com) 여기에서 yml설정을 바꿔보라 하셨는데 yml파일이 어디에 있는지 모르겠고 혹시 다른 문제로 오류가 생겼을까요?
안녕하세요! 학습 중 궁금한 내용이 있어 질문드립니다. 람다식을 사용 시 final 변수가 아니면 참조 시 오류가 발생한다고 하셨는데 그렇다면 람다식을 사용해 익명 클래스를 생성하는 것이 해당 함수가 부수 효과가 없는 함수라는 것을 보장해주는지 궁금합니다. 아니라면, 개발자가 직접 부수효과가 발생하지 않도록 신경써서 람다식을 작성해야 하는 것인가요? 감사합니다.
저는 괄호에 초점을 맞춰서 다르게 풀어보았습니다. 문자가 들어왔을 때, 괄호에 대한 스택이 비어있으면 괄호 밖에 있다고 판단하고 문자를 출력하는 방식으로 구현했습니다. 풀이에 논리적 오류가 있는지 확인해주시면 감사하겠습니다. import java.util.Scanner; import java.util.Stack; public class Main { public static String solution(String[] text) { Stack<String> bracketStack = new Stack<>(); StringBuilder answer = new StringBuilder(); for (String word : text) { if (word.equals("(")) bracketStack.push(word); else if (word.equals(")")) bracketStack.pop(); else if (bracketStack.isEmpty()) answer.append(word); } return answer.toString(); } public static void main(String[] args) { Scanner input = new Scanner(System.in); String[] text = input.next().split(""); System.out.println(solution(text)); } }
a ,b ,c .or(d) 제가 원하는 쿼리는 (a) and (b) and (c ) or (d)인데 실제 쿼리는 (a) and (b) and (c or d)이렇게 쿼리문이 나갑니다. 어떻게 해야할까요? 개별 괄호는 쳐도 다 생략이 되고 (a ,b ,c) .or(d) 이렇게도 불가한데 BooleanExpression으로는 제가 원하는 방식을 사용할 수 없을까요?