월 17,600원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨실전! Querydsl
[질문X] fields 방식이 private이여도 주입이 되는 이유
저도 잠깐 생각해봤는데,이 Projections.fields라는 건 리플렉션 방식을 이용한다고 함.뭔지는 잘 모르겠으나, 객체의 구체적인 타입을 알지 못하더라도 해당 객체의 멤버변수, 메서드 등에 접근할 수 있도록 해주는 자바의 기능이라고 함.생각해보면 private 하는 게 정말로 다른 객체에서 절대로 접근하지 못하게 할거야! 라기 보다는 유지보수, 축약하자면 캡슐화를 위해 함. 근데, 필드에 주입 할 수 있다는 것 자체가, 주입할 판이 있어야 함. 주입할 객체가 있어야 함. 그래서 비어있는 생성자가 필요한 듯.
- 해결됨실전! Querydsl
왜 메소드 이름이 bean인가요?
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]저는 bean이라 하면 뭐에 의해 관리되는 하나하나 개개의 단위? 라고 생각했어요. 스프링 빈.영속성 컨텍스트에 의해 관리되는 엔티티들도 약간 그런 느낌으로.. 근데 여기서 bean이라는 메소드 명을 들으니 뭐라고 생각해야 될 지 모르겠어요.
- 미해결실전! Querydsl
[질문 X] 스프링 부트 3.2 QueryDSL gradle 설정
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]plugins { ...... // QueryDSL 관련 명령어 id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } dependencies { ........ //QueryDSL 종속성. implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" } //QueryDSL 설정 //def generated = 'src/main/generated' def generated = layout.buildDirectory.dir("generated/querydsl").get().asFile querydsl { jpa = true querydslSourcesDir = generated } sourceSets { main.java.srcDir generated } compileQuerydsl{ options.annotationProcessorPath = configurations.querydsl } configurations { compileOnly { extendsFrom annotationProcessor } querydsl.extendsFrom compileClasspath } //def generated = 'src/main/generated'def generated = layout.buildDirectory.dir("generated/querydsl").get().asFile 이 둘의 차이는 src 폴더 안에 구현체인 Q 파일들을 넣느냐, 아니면 빌드 폴더에 넣느냐인데, 만약 이 gradle을 쓰면서 영상처럼 compileQuerydsl 하고 시작하면java: Attempt to recreate a file for type study.querydsl.entity.QTestEntity 이런 오류가 날 수 있음.그러니까, Test를 시작할 때 빌드 하면서 시작하는데, 아마도 build에 compileJava가, compileJava에 compileQuerydsl이 포함되어 있음. 그래서 이미 compileQuerydsl로 QueryDSL 파일들을 빌드 한 상태에서 시작을 하려니,저 파일을 다시 생성하려고 시도한다는 오류가 뜨는 걸로 추측됨. 근데 또 신기한게 뭔가 기록? 캐시가 남는지, QueryDSL 파일을 import 안한 상태로 뻘건줄 쭉쭉 있는 상태로 테스트 돌려서 자동으로 빌드가 따라오게끔 하면 저런 오류가 안뜸.근데 이런 아무리 알고 있는 에러이지만 저런 환경에서 코드를 짠다는 건 좀..저는 그래서 그냥 일단def generated = 'src/main/generated'여기에 Q파일을 일단 뒀다가, gitignore에 저거 등록 하고,build 할 때만 def generated = layout.buildDirectory.dir("generated/querydsl").get().asFile이걸로 바꿔놓는 걸 추천.. 저는 그렇게 했고 더 좋은 방법도 있을거임..
- 미해결실전! Querydsl
Querydsl Q클래스 생성 오류
plugins { id 'java' id 'org.springframework.boot' version '3.1.5' id 'io.spring.dependency-management' version '1.1.3' id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"}group = 'study'version = '0.0.1-SNAPSHOT'java { sourceCompatibility = '17'}configurations { compileOnly { extendsFrom annotationProcessor}}repositories { mavenCentral()}dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor"com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" testImplementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'}tasks.named('test') { useJUnitPlatform()}clean { delete file('src/main/generated')}tasks.named('bootBuildImage') { builder = 'paketobuildpacks/builder-jammy-base:latest'}tasks.named('test') { useJUnitPlatform()}//querydsl 세팅 시def querydslDir = "$buildDir/generated/querydsl"querydsl { jpa = true querydslSourcesDir = querydslDir}sourceSets { main.java.srcDir querydslDir}configurations { querydsl.extendsFrom compileClasspath}compileQuerydsl { options.annotationProcessorPath = configurations.querydsl}인프런에서 질문 & 답변을 보고 gradle 설정했는데도 오류가 계속 발생됩니다.Build and run using : Gradle 로 변경하면 발생 되는 오류 입니다.오류 : Attempt to recreate a file for type study.querydsl.entity.QHello
- 미해결실전! Querydsl
QueryDSL관련 질문입니다
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 네2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 네3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]본 강의에서도 영한님께서 JPA를 querydsl로 바꾸셨는데! 조회쿼리만 바꾸셨습니다. QueryDSL로는 주로 조회작업만 하는건가요?
- 미해결실전! Querydsl
EntityManagerFactory를 활용한 페치조인 예제 에러(해결법있음 - 이유모름)
환경 조인 - 페치 조인 강의를 듣던 중이 부분 예제를 따라 하다가 보니java.lang.illegalstateexception: specified field type [interface jakarta.persistence.entitymanagerfactory] is incompatible with resource type [jakarta.persistence.entitymanager]이라는 exception이 발생했습니다.강의에서 새로운 프로젝트를 생성하거나 파일을 생성하지 않았으므로 상단에@PersistenceContext EntityManager em; 가 있고 추가적으로@PersistenceContext EntityManagerFactory emf;를 넣어주고 테스트 코드에서emf.getPersistenceUnitUtil().isLoaded(findMember.getTeam());를 실행하였습니다. 일단 entitymanagerfactory는 yml에 있는 설정을 바탕으로 1개가 생성되고 해당 factory에서 요청에 의해 entitymanager를 생성해서 제공하는 형태라는 글을 발견하여 추가적인 의존성 주입에서 2개의 factory 생성되는 이슈가 발생해서가 아닌가 추측을 하고 우선적으로는 사용중인 em에서 factory를 가져올 수 있길래 이렇게 접근했는데em.getEntityManagerFactory().getPersistenceUnitUtil().isLoaded(findMember.getTeam());정상작동은 하긴 하지만 강사님의 경우 추가적인 entitymanagerfactory 주입에도 테스트코드가 돌아갔으므로 정확한 동작 이유를 잘 모르겠어서 혹시 확실한 이유를 알 수 있을까 하여 문의합니다.바탕
- 미해결실전! Querydsl
encrypt된 데이터의 like 검색
안녕하세요.querydsl 의 where 절을 사용하여 aes256으로 encrypt되어 저장된 db 데이터를 검색하려고 합니다.eq()일때는 가능한데 like() 검색을 어떻게 해야할지 고민이 되어 질문 드립니다.그래서 현재 생각한 방법은 where절을 사용하지 않고, Converter를 사용하여 DB에서 데이터를 전부 읽어온 다음, 복호화된 데이터를 stream으로 contains를 사용하여 like 검색과 limit, skip으로 페이징을 처리하는 방법인데요.이럴경우 데이터 양이 많아지게되면 where 조건이 없기 때문에 속도나 성능 측면에서 문제가 있을까 고민이 됩니다.현재 코드를 사용해도 문제가 없을지, 새로운 방법이 있을지 질문 드립니다.
- 미해결실전! Querydsl
querydsl 설정
스프링부트 버전 3.1.5자바 17ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ위 버전들을 사용중인데, 강의자료에 있는 querydsl로 잘 되지않아 구글링 및 질문게시판을 보다가 plugins { id 'java' id 'org.springframework.boot' version '3.1.5' id 'io.spring.dependency-management' version '1.1.3' } group = 'study' version = '0.0.1-SNAPSHOT' java { sourceCompatibility = '17' } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' // ⭐ Spring boot 3.x이상에서 QueryDsl 패키지를 정의하는 방법 implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api" //쿼리 파라미터 로그 남기기 implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.9.0' } tasks.named('test') { useJUnitPlatform() } // === ⭐ QueryDsl 빌드 옵션 (선택) === def querydslDir = "$buildDir/generated/querydsl" sourceSets { main.java.srcDirs += [ querydslDir ] } tasks.withType(JavaCompile) { options.annotationProcessorGeneratedSourcesDirectory = file(querydslDir) } clean.doLast { file(querydslDir).deleteDir() } 이렇게 설정 후 돌려보니 이렇게 설정 했을 때만 Q파일이 생성되고 잘 작동하였습니다.Build and run using을 IntelliJ IDEA로 하면 Q파일이 경로가 잘못된 것인지 생성은 되는데 import가 되지 않았습니다. 그냥 저렇게 사용하다가 '조회 API 컨트롤러 개발' 강의를 보다 QuerydslApplication을 돌려보니 오류가 나와 구글링 해보니 Build and run using을 IntelliJ IDEA로 설정해야 한다고 하더라구요 근데 그렇게 하면 또 Q파일이 에러가 나고 계속 에러가 돌고 도는 것 같습니다. Build and run using을 IntelliJ IDEA로 설정하려면 build.gradle을 어떻게 작성해야 하나요??
- 미해결실전! Querydsl
@Type(JsonType.claa) 어노테이션 인식 불가 문제.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]안녕하세요. 강사님.Entity 가 가지고 있는 필드중에 아래와 같은 필드가있습니다.//Entity @Type(JsonType.class) @Column(name ="INFO", columnDefi...) private Setting setting; ..위와 같이 엔티티에 oracle 19c 의 VARCHAR2 타입에 json check 를 활용하여 json 타입의 필드를 사용하고있습니다. 아래와 같이 JPA 를 활용하여 데이터를 업데이트할때는 시리얼라이제이션에서 별다른 문제가없는데요Entity a = em.find(id); a.setSetting(settingDto); 이후에 정상적인 업데이트 쿼리후 Setting 객체가 json String 형태로 INFO 컬럼에 정상적으로 업데이트됨.문제는 QueryDSL 형태로 update를 할때입니다.queryFactory.update(entity) .set(qEntity.setting, settingDto) .execute()위와같이 변경하여 업데이트를 시도하면 org.hibernate.type.descriptor.java.spi.JdbcTypeRecommendationException: Could not determine recommended JdbcType for 'com. .. .Setting'오류가 발생합니다. 추측하건데 @Type(JsonType.clss) 관련 Entity 의 컬럼 어노테이션을 참조하지 못하는것 같은데 혹시 문제를 겪어보셨거나 해결에 도움이 될만한 내용이있을까해서 질문드려봅니다.감사합니다.
- 미해결실전! Querydsl
Response에 값이 채워지지 않습니다!
안녕하세요! 제가 지금 진행 중인 프로젝트가 있는 데 어려움을 겪어서 질문 드립니다!queryDsl을 사용해서 DTO로 바로 조회도 되고 값이 담겨져 있는 것도 로그를 찍어서 확인할 수 있습니다. 근데 PostMan이나 스웨거로 값을 반환받았을 때 isAuthenticated 값은 잘 채워져서 나오는 데 CulturalEventDetail값이 자꾸 null로 반환이 됩니다! 아무리 찾아봐도 답이 안 나와서 질문 드립니다..아래는 코드 입니다! @Getter @Builder @NoArgsConstructor @AllArgsConstructor @ToString public class CulturalEventDetailsResponseDTO { private CulturalEventDetail culturalEventDetail; private boolean isAuthenticated; } public CulturalEventDetailsResponseDTO getCulturalEventDetails(final int culturalEventId, final int userId) { return queryFactory.select(Projections.fields(CulturalEventDetailsResponseDTO.class, culturalEvent.culturalEventDetail, visitAuth.isAuthenticated)) .from(culturalEvent) .leftJoin(visitAuth) .on( culturalEvent.id.eq(visitAuth.culturalEvent.id), visitAuth.user.id.eq(userId)) .where( culturalEvent.id.eq(culturalEventId) ) .fetchOne(); } public CulturalEventDetailsResponseDTO getCulturalEventDetails(final int culturalEventId, final User user) { final CulturalEventDetailsResponseDTO culturalEventDetails = culturalEventQueryRepository.getCulturalEventDetails(culturalEventId, user.getId()); culturalEventRepository.updateVisitCount(culturalEventId); log.info("culturalEventDetails = {}", culturalEventDetails); return culturalEventDetails; } 2023-11-12T04:44:46.017+09:00 INFO 10556 --- [nio-8080-exec-1] e.c.c.s.c.CulturalEventService : culturalEventDetails = CulturalEventDetailsResponseDTO(culturalEventDetail=CulturalEventDetail( category=CONCERT, d, ....), isAuthenticated=true) @RestController @RequiredArgsConstructor @RequestMapping("/cultural-event") public class CulturalEventController { private final CulturalEventService culturalEventService; @GetMapping("/{culturalEventId}") public ResponseEntity<CulturalEventDetailsResponseDTO> getCulturalEventDetails(final @PathVariable int culturalEventId, final @AuthenticationPrincipal User user) { return ResponseEntity.ok(culturalEventService.getCulturalEventDetails(culturalEventId, user)); }
- 미해결실전! Querydsl
on()구문 질문입니다
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]아래의 두 코드는 방식의 차이일뿐 같다라고 봐도 무방할까요?- 연관관계가 있는 경우from(member).join(member.team, team)- 연관관계가 없는 경우from(member).join(team).on(member.team.id.eq(team.id))
- 미해결실전! Querydsl
Querydsl 버전 관련
안녕하세요! Querydsl 을 공부한 후 현재 인턴으로 있는 회사에서 프로젝트에 적용해보려고 합니다. 근데 해당 프로젝트의 스프링 버전이 2.2.0 release 버전인데 해당 버전에서 Querydsl은 어떻게 해야하는지 여쭤볼 수 있을까요 ?
- 미해결실전! Querydsl
정렬 조건에 대해 질문이 있습니다.
public enum Tier { CHALLENGER("challenger"), GRANDMASTER("grandmaster"), MASTER("master"), DIAMOND("diamond"), EMERALD("emerald"), PLATINUM("platinum"), GOLD("gold"), SILVER("silver"), BRONZE("bronze"), IRON("iron"), NULL("null"); private final String tier; Tier(String tier) { this.tier = tier; } }이런 enum을 필드로 가지고 있는 entity가 있습니다.public class MyEntity { ... @NotNull @Column(name = "queue", columnDefinition = "VARCHAR(20)") @Enumerated(EnumType.STRING) private Tier queue; ... } 그런데 querydsl로 이 enum기준으로 custom sort를 할 경우에는 어떻게 해야하나요?예를 들면 enum Tier에 적혀있는 순서대로 CHALLENGER > GRANDMASTER > ... > NULL 순서대로 정렬할 때 어떻게 해야하는지 궁금합니다!
- 미해결실전! Querydsl
QuerydslApplicationTests 오류
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not prepare statement Caused by: org.hibernate.exception.SQLGrammarException: could not prepare statement Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Sequence "HIBERNATE_SEQUENCE" not found; SQL statement:call next value for hibernate_sequence [90036-199] h2는 1.4.199 사용중이며 application.yml파일도 똑같이 했는데 계속 저런 오류가 뜹니다..
- 미해결실전! Querydsl
어그리게이트간 id 참조를 할 때는 querydsl 어떻게 잘 활용할 수 있을까요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예[질문 내용]https://www.popit.kr/id%EB%A1%9C-%EB%8B%A4%EB%A5%B8-%EC%95%A0%EA%B7%B8%EB%A6%AC%EA%B2%8C%EC%9E%87%EC%9D%84-%EC%B0%B8%EC%A1%B0%ED%95%98%EB%9D%BC/이 글을 보고 다른 어그리게이트 간에는 id 참조를 한다고 하면querydsl 을 통해서 다른 어그리게이트간 join 은 어떻게 활용할 수 있나요?예를 들어서 Order, Review 라는 도메인이 아래와 같다고 해볼게요. @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Review { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column private String content; @Column private int rate; private Long orderId; public Review(final String content, final int rate) { this.content = content; this.rate = rate; } }@Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Order { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column private String name; @Column private String orderStatus; @Column private LocalDateTime createdAt; public Order(final String name, final String orderStatus) { this.name = name; this.orderStatus = orderStatus; this.createdAt = LocalDateTime.now(); } } 이때 생성되는 QType 에는 두 엔티티간의 참조 관계를 표현할 수 없는데 이런 경우에는 join 등을 어떻게 활용할 수 있을까요제가 "어그리게이트간 id 참조를 해라!" 잘못 이해하고 있는 것일까요?
- 미해결실전! Querydsl
inner join 인 경우 join 문이 없어도 되는 경우
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)예[질문 내용]queryDsl 강의 중 조인편을 보면서 한가지 실험을 해봤습니다.@Test void 팀A에_소속된_모든_멤버를_조회힌다() { List<Member> found = jpaQueryFactory.selectFrom(member) .where(member.team.name.eq("teamA")) .fetch(); assertThat(found) .map(Member::getTeam) .extracting("name") .allMatch(teamName -> teamName.equals("teamA")); } @Test void 조인을_통해_팀A에_소속된_모든_멤버를_조회힌다() { List<Member> found = jpaQueryFactory.selectFrom(member) .join(member.team, team) .where(team.name.eq("teamA")) .fetch(); assertThat(found) .map(Member::getTeam) .extracting("name") .allMatch(teamName -> teamName.equals("teamA")); }첫번째 테스트는 join 문 없이 QType 을 활용해서 where에 필요한 조건을 작성하였구요두번째 테스트는 join 메서드를 활용한 것 입니다.테스트 결과도 같고 실행 후 실제 수행된 쿼리도 동일하더라구요이런 경우에는 어떤 방법이 더 적절할까요?
- 미해결실전! Querydsl
QueryDSL내부 동작관련 질문입니다
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 직접적인 관련은 없습니다2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]QueryDSL은 내부적으로 JPQL을 사용해서 DB와 통신을 하느건가요?
- 미해결실전! Querydsl
contextLoad에 작성하신 테스트 관련 질문입니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]현재 본 강의까지 H2설정을 application.yml에 하지 않았는데 contextLoads()에 작성한 테스트가 어떻게 성공적으로 수행되는 건가요?
- 미해결실전! Querydsl
JPQL vs QueryDSL
JPQL 보다 QueryDSL 사용하는게 좀더 오류를 빨리 잡을 수 있어서 QueryDSL을 사용하는게 더 좋을 것 같은데, QueryDSL 보다 JPQL이 유용한 경우가 있을까요?
- 해결됨실전! Querydsl
PageableExecutionUtils.getPage 의 최적화 로직만 따로 뺀 count 메소드입니다.
갱신된 강의자료에도 나와 있듯이, fetchResult, fetchCount 등의 메소드는 deprecated 예정입니다. 또한 해당 메소드는 Page 타입을 반환하기 때문에 Page 타입을 직접적으로 조작해야 한다는 제약이 있습니다. 이걸 잘 쓰면 되는데, Page 의 시작번호 등 제약도 있어서 저는 회사에서 Page 를 따로 만들어서 사용하거든요. 그래서 search 메소드와 count 메소드는 항상 분리하고 있습니다.2. 그런 점에서 count 만 최적화하는 로직만 베껴서 만든 최적화 메소드입니다.실제로 count 구문을 실행하기 위한 메소드입니다. 필요에 따라서 public 으로 만들어도 될 것 같네요. // count 실행 메소드 private Long countByCond(MemberSearchCond cond) { return query .select(member.countDistinct()) .from(member) .where( usernameEq(cond.getUsername()), teamNameEq(cond.getTeamName()), ageGoe(cond.getAgeGoe()), ageLoe(cond.getAgeLoe()) ) .fetchOne(); } 최적화 로직을 베낀 메소드입니다. 스프링 데이터 JPA 는 아래 코드와 같이 page, size 값이 null 이 아니고, 적절한 범위에 있는지를 판단하여 isPaged 라는 분기를 만듭니다. 참고로 코드를 분석하면서 내린 뇌피셜이니 혹시 틀리다면 말씀해주세요. page 가 0 이 아니라 1 부터 시작하는 건 제 취향입니다. 회사에서 그렇게 쓰고 있거든요. 필요에 따라 0 부터 시작하도록 바꾸는 건 어렵지 않을 것 같습니다.public Long countByCondOptimization(List<?> content, MemberSearchCond cond, Long page, Long size) { boolean isPaged = page != null && size != null && page > 0 && size > 0; long offset = isPaged ? (page - 1) * size : 0L; long contentSize = content.size(); if (!isPaged || offset == 0) { if (!isPaged || size > contentSize) { return contentSize; } return this.countByCond(cond); } if (contentSize != 0 && size > contentSize) { return offset + contentSize; } return this.countByCond(cond); } 이렇게 하여 count 쿼리를 리스트 조회 쿼리와 분리하여 재사용성을 높이면서, 성능도 최적화할 수 있습니다.감사합니다.