inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

173만명의 커뮤니티!! 함께 토론해봐요.

스프링 부트3와 카운트 쿼리 분리

해결됨

실전! 스프링 데이터 JPA

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 안녕하세요. 카운트 쿼리 분리 부분을 듣는 도중에 카운트 쿼리에 LEFT JOIN이 사용되는 결과를 확인하기 위해 다음처럼 코드를 작성하였습니다. public interface MemberRepository extends JpaRepository<Member, Long> { @Query(value = "select m from Member m left join m.team t") Page<Member> findByAge(int age, Pageable pageable); ... } @Test public void paging() throws Exception { //given memberRepository.save(new Member("member1", 10)); memberRepository.save(new Member("member2", 10)); memberRepository.save(new Member("member3", 10)); memberRepository.save(new Member("member4", 10)); memberRepository.save(new Member("member5", 10)); //when PageRequest pageRequest = PageRequest.of(0, 3, Sort.by(Sort.Direction.ASC, "username")); Page<Member> page = memberRepository.findByAge(10, pageRequest); //then List<Member> content = page.getContent(); assertThat(content.size()).isEqualTo(3); assertThat(page.getTotalElements()).isEqualTo(5); assertThat(page.getNumber()).isEqualTo(0); assertThat(page.getTotalPages()).isEqualTo(2); assertThat(page.isFirst()).isTrue(); assertThat(page.hasNext()).isTrue(); } 그런데 결과는 강의와는 달리 카운트 쿼리에 LEFT JOIN 이 사용되지 않았고, 심지어 JPQL select m from Member m left join m.team t 을 @Query에 작성했음에도 조회 쿼리도 LEFT JOIN을 사용하지 않은 것을 확인했습니다. 이후 스프링 부트 3 이하 버전에서 동일한 코드로 실행해보니 강의와 동일한 결과를 얻을 수 있었습니다. 스프링 부트 3 부터 적용된 스프링 데이터 JPA 에서는 이러한 부분의 최적화를 자동으로 제공하는 것일까요?

  • java
  • spring
  • spring-boot
  • jpa
조약돌 댓글 1 좋아요 1 조회수 775

자바 공부법

미해결

즐거운 자바

안녕하세요. 백엔드 개발자 희망하고 있습니다. 자바 독학 공부 시작했는데 기본문법 예제들은 혼자 짤 수 있는데 객체지향/3 로또 부분부터 어렵네요. 구구단, 별찍기 하다가 로또 구현할 수 있을때까지 공부 방법이 궁금합니다. ㅠ.ㅠ 자바 공부 방법 알려주세요 ㅠㅠㅠ 지금은 강사님 강의 보고 이해가 부족하다는 부분 이론서 보면서 나가고있습니다. 이론서에 나와있는 문제들도 타이핑 하면서 진행하구 있습니다. 길게 코드 작성할 수 있을때까지 자바 공부 방법 알려주세요.

  • java
  • 자바공부
댓글 2 좋아요 1 조회수 1730

16강 mysqldb 연동이 안되어요

해결됨

스프링 프레임워크는 내 손에 [스프1탄]

mysql cmd로 서버연결하는거 안되네요 오류가 자꾸 나요 cmd창이 아주 순식간에 떳다가 사라져요 그래서 동영상으로 찍고 캡쳐했어요 해결방법 찾아보는데 너무 힘들어서 질문 올립니다 ㅠ 아 참고로 맥북에 부트캠프로 윈도우 사용중입니다 그래서 그런걸까요? 그냥 cmd랑 mysql 전부 다 잘 되는데 저것만 실행이 안되네요..

  • jsp
  • spring
  • mvc
  • spring-security
xldals 댓글 2 좋아요 0 조회수 340

스프1탄을 보기 전에 나프1,2탄은 필수일까요?

미해결

스프링 프레임워크는 내 손에 [스프1탄]

안녕하세요. 현재 회사에서 일하고 있는 초보개발자입니다. 현재 강사님의 로드맵을 따라서 모든 강의를 사서 차근차근 보고있는 중인데, 현재 회사에서 스프링으로 신규 프로젝트를 진행할 것 같아서 스프1탄을 먼저 보려고 하는데, 나프1탄과 나프2탄을 필수적으로 보고 스프1탄을 봐야할까요? 나프1탄과 나프2탄은 보기에는 시간적으로 여유가 많이 없을 것 같아서 질문드립니다ㅠ

  • jsp
  • spring
  • mvc
  • spring-security
김찹귤 댓글 1 좋아요 0 조회수 342

UrlSecurityMetadataSource 클래스의 reload() 메서드 질문이 있습니다!

미해결

스프링 시큐리티

좋은 강의 잘 보고 있습니다. 감사합니다. 섹션 5. "실전프로젝트 - 인가 프로세스 DB 연동 웹 계층 구현"의 "6) 웹 기반 인가처리 실시간 반영하기" 강의를 보다 의문이 생겨 질문을 남기게 되었습니다. UrlSecurityMetadataSource 클래스에 다음과 같은 reload() 함수가 있습니다. 여기서 "securityResourceService.getResourceList()"의 반환값과 "requestMap"의 타입이 똑같으니 requestMap = securityResourceService.getResourceList(); 으로 바로 객체를 할당하면 될 것 같았는데, Iterator를 사용하여 put 하시는 것이 성능상의 문제나 다른 이슈가 있어서 이렇게 작성을 하신건지 의문이 들었습니다. 새로운 List를 바로 할당하지 않고, 기존 List 객체를 유지하신 이유가 궁금합니다! 감사합니다. // UrlSecurityMetadataSource 클래스 public void reload() { LinkedHashMap<RequestMatcher, List<ConfigAttribute>> reloadedMap = securityResourceService.getResourceList(); Iterator<Map.Entry<RequestMatcher, List<ConfigAttribute>>> iterator = reloadedMap.entrySet().iterator(); requestMap.clear(); while (iterator.hasNext()) { Map.Entry<RequestMatcher, List<ConfigAttribute>> entry = iterator.next(); requestMap.put(entry.getKey(), entry.getValue()); } }

  • java
  • spring-boot
  • spring-security
댓글 1 좋아요 0 조회수 353

spring 2.x - Querydsl 이슈있는분들 참고하세요

미해결

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] plugins { id 'org.springframework.boot' version '2.6.5' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' ext["hibernate.version"] = " 5.6.5.Final " configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'javax.validation:validation-api' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5' //JdbcTemplate 추가 //implementation 'org.springframework.boot:spring-boot-starter-jdbc' //MyBatis 추가 implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0' //JPA, 스프링 데이터 JPA 추가 implementation 'org.springframework.boot:spring-boot-starter-data-jpa' //Querydsl 추가 implementation 'com.querydsl:querydsl-jpa' annotationProcessor "com.querydsl:querydsl-apt:$ { dependencyManagement.importedProperties['querydsl.version'] } :jpa" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" //H2 데이터베이스 추가 runtimeOnly 'com.h2database:h2' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' //테스트에서 lombok 사용 testCompileOnly 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' } tasks.named('test') { useJUnitPlatform() } //querydsl 추가 //def querydslDir = '$buildDir/generated' def querydslDir = "src/main/generated" //clean { // delete file(generated) //} querydsl { library = "com.querydsl:querydsl-apt" jpa = true querydslSourcesDir = querydslDir } sourceSets { main { java { srcDirs = ['src/main/java', querydslDir] } } } compileQuerydsl { options.annotationProcessorPath = configurations.querydsl } configurations { querydsl.extendsFrom compileClasspath } 강사님이 올려주신 내용 + 구글링 + 직접 수정했습니다. 간혹, 빌드는 되는데 generated 파일에 QClass 안보이시는 분들은 queryDsl 저장되는 경로에 $buildDir 대신 'src/main/'으로 해보세요

  • java
  • spring
  • spring-boot
  • jpa
henn36 댓글 1 좋아요 4 조회수 1264

H2 가 아닌 mysql DB 를 사용중인데 조그만한 질문이 있습니다.

미해결

호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)

재기동을 했음에도 불구하고 쿠키값이 그대로 남아있는 현상이 있어서 원하는 요청이 정상적으로 이루어지지 않았던 문제가 있었습니다. 이상해서 원인을 파악하다보니 현재 전 mysql DB 를 연결하여 사용중이었고, 호돌맨님은 H2 DB 를 사용중이시더라구요. 그래서 재기동을 할때마다 쿠키값이 삭제되고 다시 생성이 되지 않았던 건데 혹시 이런 상황에서 조언이 될 만한 링크나 키워드를 알려주실 수 있으실까요?? 제가 직접 삽질하면서 찾아보고 해결해보려구요 ㅠㅠ (현재는 매번 재기동 할때마다 쿠키값을 직접 삭제해주면서 강의를 따라가고 있습니다)

  • vue.js
  • aws
  • spring-boot
  • jpa
  • spring-security
leeseongju 댓글 1 좋아요 1 조회수 502

invalidSessionUrl, expiredUrl

해결됨

스프링 시큐리티

아래와 같이 최대 허용 가능 세션 수를 설정하고, 테스트 해보려고 했는데 /invalid 나 /expired 페이지로 이동하지 않고 /login 페이지로 이동하는데 뭐가 문제인지 모르겠습니다. http .sessionManagement() .invalidSessionUrl("/invalid") .maximumSessions(1) .maxSessionsPreventsLogin(true) // false도 테스트 해봄 .expiredUrl("/expired");

  • java
  • spring-boot
  • spring-security
cozyrust 댓글 2 좋아요 0 조회수 1078

JPA 특징 중 자동 업데이트 관련

미해결

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

주문 서비스 개발 부분 강의를 듣다가 궁금한 점이 있어 질문드립니다. 주문 취소(OrderService.cancelOrder) 부분에서order.cancel() 만 작성하면 JPA 특징으로 인해, 데이터 업데이트 관련 쿼리 로직 없이 자동으로 업데이트 된다고 하셨는데요. 주문 생성(OrderService.order)의 EntityManager 가 사용된 orderRepository.save (order);  와 혼동이 와서 질문 남깁니다. 주문 취소 order.cancel() 메서드를 타면서 엔티티의 값(status, count 등) 변경 내역이 자동으로 업데이트 되는 것이라고 하면, 주문 생성도 Order.createOrder(member, delivery, orderItem); 를 타면서 엔티티의 값들을 설정하기 때문에 orderRepository.save (order); 를 사용하지 않아도 되는게 아닌가 라는 생각이 듭니다. 제가 JPA 를 잘 몰라서 혼란이 오는 것 같은데.. 쿼리는 직접 작성하지 않아도 업데이트/저장/삭제 등 DB 조작이 일어나려면 EntityManager 를 통해야 된다고 생각하고 있었습니다. 주문 취소는 EntityManager 없이 업데이트 되고, 주문 생성은 EntityManager의 persist() 를 사용해서 저장하는 것 이 2가지 차이점에 대해서 설명 부탁드립니다! 감사합니다 :)

  • java
  • spring
  • 웹앱
  • spring-boot
  • jpa
빈빈 댓글 1 좋아요 2 조회수 510

이전에 발급된 토큰

미해결

스프링 시큐리티

9:20초 쯤에 이전에 발급된 토큰이 있다고 말씀해주셨는데 이전이라는게 언제를 말씀하시는건가요 ? 서버를 재가동시키고 아무것도 안하고 지금 요청만 보냈을뿐인데 어떻게 갑자기 CSRF관련 토큰이 있는건가요?? 저는 강의 똑같이 따라했는데 csrfToken값이 null이나옵니다.

  • java
  • spring-boot
  • spring-security
김태희 댓글 2 좋아요 0 조회수 567

20:00 부분에 공격자가 갑자기 어떻게 JSESSIONID를 가지고있는건가요?

미해결

스프링 시큐리티

PPT 설명이 다 끝나고 실습에 들어가는데 갑자기 JSESSIONID를 공격자가 로그인을 하지않았는데도 가지고 있을수가 있는건가요?? 혹시 로그인 과정을 했다고 가정하시고 생략하신건가요?? 그리고 Session ID를 이미 가지고 있는데 Login 페이지를 접근한다는것 자체가 조금 말이 안되는 상황인것 같은데 이 부분에 대해서는 다른 강의에서 다루고 있나요? 혹시 생략하신거라면, 어떠한 방식(자막, 공지, etc..)으로든 알려주시면 감사할것 같습니다. 듣는 수강생 입장에서는 "뜬금없이 갑자기 로그인이 되어있네"라는 생각을 할 수밖에 없는것 같습니다. 그렇게되면 그 전에 로그인을 했는데 내가 놓친건가?라고 다시보게되고 저같은 경우에는 왠만해선 질문을 안하려는 성격이여서 계속 제가 놓쳤다고 생각하고 시간을 쓰기때문에 이렇게 뭔가 결국 생략했다라는걸 알게되면 매우 허탈합니다. 그래서 이게 Interrupt가 걸리고 강의에 집중하는데 힘이듭니다. 이런 부분이 한두군데가 아니여서 이렇게 말씀드립니다. 부탁드리겠습니다.

  • java
  • spring-boot
  • spring-security
김태희 댓글 3 좋아요 0 조회수 925

JWT + Oauth2 붙이기

미해결

스프링부트 시큐리티 & JWT 강의

안녕하세요. 강사님! 수업 정말 잘 들었습니다! 비전공자로써 3개월째인데 JWT 강의 중에 정말 이해가 잘 되었습니다!!! 진심으로 감사합니다~~ 다름이 아니라 더 나아가서, JWT와 Oauth2를 붙이려고 하는데 JWT 강의 초반에 기존의 Oauth2 방식을 사용하지 않고 다른 방식을 써야 된다고 하셔서 질문합니다. 어떤 부분이 달라져야할지 전혀 감이 안 오는데, 제가 조금 참고할만한 자료가 있을까요? 혹시 JWT+Oauth를 붙이려고 할 때 코드가 많이 변경될까요? (혹시 강의 제작하실 생각 없으신가요...ㅎㅎ)

  • spring
  • spring-security
  • jwt
  • oauth2
Lee jeonghui 댓글 1 좋아요 0 조회수 794

시큐리티 1강 환경설정 10분 요렇

미해결

스프링부트 시큐리티 & JWT 강의

configureViewResolvers 을 오버라이딩 했을때 내부구성을 요렇게 바꿔 주세요를 하셨을때 요렇게를 어떻게 요렇게 바꾸나요?

  • spring
  • spring-security
  • jwt
seongbin 댓글 2 좋아요 0 조회수 807

19:04 초 where in 쿼리 대신 where array_conatins 쿼리가 나왔습니다. (스프링 부트 3.1)

해결됨

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 현재 스프링 부트 3.1 로 강의를 따라가고 있습니다. default_batch_fetch_size:10 을 설정해서 나가는 쿼리가 줄어드는 것을 확인했습니다만, 쿼리가 두 개가 아니고 총 세 개가 나왔습니다. 023-06-13T23:24:02.666+09:00 DEBUG 68750 --- [nio-8080-exec-5] org.hibernate.SQL : select o1_0.order_id, d1_0.delivery_id, d1_0.city, d1_0.street, d1_0.zipcode, d1_0.status, m1_0.memeber_id, m1_0.city, m1_0.street, m1_0.zipcode, m1_0.name, o1_0.order_date, o1_0.status from orders o1_0 join member m1_0 on m1_0.memeber_id=o1_0.member_id join delivery d1_0 on d1_0.delivery_id=o1_0.delivery_id offset ? rows fetch first ? rows only 2023-06-13T23:24:02.676+09:00 INFO 68750 --- [nio-8080-exec-5] p6spy : #1686666242676 | took 2ms | statement | connection 8| url jdbc:h2:tcp://localhost/~/springbootjpa select o1_0.order_id,d1_0.delivery_id,d1_0.city,d1_0.street,d1_0.zipcode,d1_0.status,m1_0.memeber_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name,o1_0.order_date,o1_0.status from orders o1_0 join member m1_0 on m1_0.memeber_id=o1_0.member_id join delivery d1_0 on d1_0.delivery_id=o1_0.delivery_id offset ? rows fetch first ? rows only select o1_0.order_id,d1_0.delivery_id,d1_0.city,d1_0.street,d1_0.zipcode,d1_0.status,m1_0.memeber_id,m1_0.city,m1_0.street,m1_0.zipcode,m1_0.name,o1_0.order_date,o1_0.status from orders o1_0 join member m1_0 on m1_0.memeber_id=o1_0.member_id join delivery d1_0 on d1_0.delivery_id=o1_0.delivery_id offset 0 rows fetch first 100 rows only; 2023-06-13T23:24:02.681+09:00 DEBUG 68750 --- [nio-8080-exec-5] org.hibernate.SQL : select o1_0.order_id, o1_0.order_item_id, o1_0.count, o1_0.item_id, o1_0.order_price from order_item o1_0 where array_contains(?,o1_0.order_id) 2023-06-13T23:24:02.689+09:00 INFO 68750 --- [nio-8080-exec-5] p6spy : #1686666242689 | took 0ms | statement | connection 8| url jdbc:h2:tcp://localhost/~/springbootjpa select o1_0.order_id,o1_0.order_item_id,o1_0.count,o1_0.item_id,o1_0.order_price from order_item o1_0 where array_contains(?,o1_0.order_id) select o1_0.order_id,o1_0.order_item_id,o1_0.count,o1_0.item_id,o1_0.order_price from order_item o1_0 where array_contains('ar2: ARRAY [CAST(1 AS BIGINT), CAST(2 AS BIGINT), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL]',o1_0.order_id); 2023-06-13T23:24:02.690+09:00 DEBUG 68750 --- [nio-8080-exec-5] org.hibernate.SQL : select i1_0.item_id, i1_0.dtype, i1_0.category_item_id, i1_0.name, i1_0.price, i1_0.stock_quantity, i1_0.author, i1_0.isbn, i1_0.artist, i1_0.etc from item i1_0 where array_contains(?,i1_0.item_id) 2023-06-13T23:24:02.691+09:00 INFO 68750 --- [nio-8080-exec-5] p6spy : #1686666242691 | took 0ms | statement | connection 8| url jdbc:h2:tcp://localhost/~/springbootjpa select i1_0.item_id,i1_0.dtype,i1_0.category_item_id,i1_0.name,i1_0.price,i1_0.stock_quantity,i1_0.author,i1_0.isbn,i1_0.artist,i1_0.etc from item i1_0 where array_contains(?,i1_0.item_id) select i1_0.item_id,i1_0.dtype,i1_0.category_item_id,i1_0.name,i1_0.price,i1_0.stock_quantity,i1_0.author,i1_0.isbn,i1_0.artist,i1_0.etc from item i1_0 where array_contains('ar3: ARRAY [CAST(1 AS BIGINT), CAST(2 AS BIGINT), CAST(3 AS BIGINT), CAST(4 AS BIGINT), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL]',i1_0.item_id); 수강 중에 제가 따라 작성한 코드를 스프링부트 2.4.1에 그대로 옮겨보니 강의 내용대로 where in 쿼리가 나오는 것을 확인했습니다. 스프링부트 버전 차이에서 나오는 쿼리가 달라진 것 같은데, 제 생각이 맞을까요? 답변 확인 : 빠르게 답변해주셔서 감사합니다!! 덕분에 array_contains 로 최적화된 이유를 쉽게 이해할 수 있었습니다. (Hibernate에서 최적화를 했었었군요!) 아 그리고 강의 내용에서 쿼리 세 개 나온다는 것을 확인했습니다(잘못 본 것에 대해 질문글에서 수정을 해놨어야 했는데 빼놓지 않았었네요 ㅠㅠ) 다시 한번 상세한 답변 정말 감사드립니다.

  • java
  • spring
  • spring-boot
  • jpa
말랑한참깨 댓글 1 좋아요 1 조회수 1931

혹시 join 자체도 특정 조건에 따라 동적으로 작용되게 할 수 있나요?

미해결

실전! Querydsl

안녕하세요. where 조건을 동적으로 생성해주는 부분에 대해서는 충분히 이해가 되었습니다. 그런데 혹시 특정 condition 값에 따라 join을 해줘야하는 테이블이 다른 경우라면 어떻게 처리되어야 할지 모르겠어서 글을 남기게 되었습니다. condition조건에 teamName이 있을 때만 team을 조인해주고 싶은데 join 구문을 동적으로 처리할 수 있는 좋은 방법이 어떤 것인지 질문드립니다. 😭 감사합니다.

  • java
  • jpa
chaerin920 댓글 1 좋아요 0 조회수 1120

로그인시 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 cause java.lang.NullPointerException: null at 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
  • spring-security
  • jwt
유요한 댓글 1 좋아요 0 조회수 1565

update쿼리로 인한 영속성컨텍스트 불일치

해결됨

실전! Querydsl

[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 수정, 삭제 벌크 연산의 6:20 부분에서 update쿼리로 인한 영속성컨텍스트 문제를 설명해주셨는데요. 전 강의에서 em.flush()실행되는 조건들을 설명해주실 때, 직접 호출 시 트랜잭션 커밋 시 JPQL쿼리 실행 시 em.flush()가 실행된다고 설명해주신 것으로 기억하고 있습니다. querydsl도 결국 JPQL기반으로 작동된다고 알고 있는데, querydsl을 통한 select쿼리 실행을 하면 자동으로 em.flush()가 실행되지 않고, 직접 해주어야 하는 메커니즘이 궁금합니다!

  • java
  • jpa
Dompoo 댓글 1 좋아요 1 조회수 526

build.gradle 빌드 실패 에러(JDK 17.0.6, Spring boot 3.0.7)

미해결

스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

안녕하세요, build.gradle의 빌드 실패가 나서 문의드립니다. JDK 버전은 다음과 같이 17.0.6입니다. 그리고 인텔리제이 설정은 다음과 같습니다. java 컴파일러 설정 2. 빌드 도구 설정 3. 프로젝트 설정 마지막으로 처음 프로젝트를 다운로드 받았던 설정은 다음과 같습니다.(spring boot 3.0.7 버전 사용) 처음 build.gradle을 실행할 때부터 에러 로그 하나도 없이 그냥 빌드 실패했다는 에러가 뜹니다. 컴퓨터를 여러번 껐다가 켜봐도 여전히 같은 에러가 뜹니다. 인텔리제이와 스프링이 완전 처음이라서 이 에러를 어떻게 해결해야 하는지 모르겠습니다. 커뮤니티의 다른 글들을 참고해봐도 딱히 도움이 되지는 않는 것 같습니다. 도와주시면 너무 감사하겠습니다.

  • java
  • spring
  • mvc
  • spring-boot
spring study 댓글 4 좋아요 0 조회수 6254

다음 강의 또 언제 나오나요

미해결

스프링 프레임워크는 내 손에 [스프2탄]

ㅠㅠ 6월 5일인데 언제나오나요

  • spring
  • jquery
  • mvc
  • jpa
  • spring-security
시골햄스터 댓글 2 좋아요 0 조회수 624

인기 태그

인프런 TOP Writers

주간 인기글