월 17,600원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결실전! Querydsl
특정 필드의 그룹별 최댓값 조회와 where절에 대한 List 사용 방법
안녕하세요. 강의를 들으면서 프로젝트를 진행하고 있다가 막히는 부분이 있어서 질문드립니다. 두서 없는 질문이어서 먼저 죄송합니다. 1. 첫번째는 https://www.inflearn.com/questions/14139 와 비슷한 질문입니다. 지금 하고 있는 프로젝트에서 상품에 대한 테이블은 다음과 같습니다. id price discountPrice shopId 1 10000 9000 1 2 12000 10000 1 3 8000 7500 1 4 10000 9900 2 이때 discountPrice와 price로 할인율을 계산하였는데요. shopId별로 가장 할인율이 높은 것을 1개 뽑고 그 뽑은 것들 중에서 할인율이 높은 순으로 10개를 뽑고 싶습니다. 할인율은 (price-discountPrice)/price * 100 으로 계산하였습니다. queryDSL에서는 from에 대한 서브쿼리를 지원하지 않아 위의 질문처럼 2개 쿼리를 쓰거나 네이티브 쿼리를 쓰려고 하는데요. 이 상황에서 2개 쿼리를 쓴다는게 어떻게 써야하는지 잘 모르겠어서 질문 드립니다. 또 다음 https://helloino.tistory.com/120https://pepperoni.netlify.app/mysql%EC%97%90%EC%84%9C%20%EA%B7%B8%EB%A3%B9%EB%B3%84%20%EC%B5%9C%EC%8B%A0%20%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0/두 개의 자료를 참조하여 다음과 같이 만들었습니다. 할인율을 직접 보려고 rate라는 걸 추가했는데 0으로 나오네요... 왜 안되는지도 궁금합니다 QProduct p1 = new QProduct("p1");QProduct p2 = new QProduct("p2");return queryFactory.select(Projections.fields(ProductTmp.class, shop.id.as("shopId"), shop.name.as("shopName"), p1.id, p1.name, p1.price, p1.discountedPrice, p1.price.subtract(p1.discountedPrice).divide(p1.price).multiply(100L).as("rate"), p1.image)) .from(p1) .innerJoin(p1.shop, shop) .leftJoin(p2) .on(p1.shop.id.eq(p2.shop.id) .and(p1.price.subtract(p1.discountedPrice).mod(p1.price).multiply(100L) .lt(p2.price.subtract(p2.discountedPrice).mod(p2.price).multiply(100L)))) .where(p2.id.isNull()) .orderBy(p1.price.subtract(p1.discountedPrice).mod(p1.price).multiply(100L).desc()) .limit(10) .fetch(); 2. 하고 있는 프로젝트에서 Shop 이란 Entity 안에는 List<String>category가 있습니다. 그런데 DB로 들어갈때는 해당 List의 요소들을 꺼내서 ,(콤마)로 이어서 하나의 String으로 만들어 DB에 넣어주고 DB에서 꺼낼때는 ,(콤마) 기준으로 나누어서 List<String>으로 꺼내줍니다. 이때 저는 입력으로 들어오는 String category가 shop의 category 안에 있는지 판단하고 이것을 where 절에 넣고 싶어서 다음을 구현했습니다. public BooleanExpression eqCategory(String category) { return hasText(category) ? shop.category.contains(category) : null;}.where(eqCategory(category)) 그런데 해당 에러가 뜨면서 되지 않습니다. java.lang.NullPointerException: Cannot invoke "org.hibernate.persister.collection.QueryableCollection.getElementPersister()" because "queryableCollection" is null shop.category.getType()은 interface java.util.List가 나오고 shop.category.getClass()는 class com.querydsl.core.types.dsl.ListPath가 나왔습니다. queryDSL에서는 List안에 있는지 판단하는게 지원이 안되는지 궁굼하고 이런 경우에는 어떻게 해결해야 하는지 궁금합니다.
- 미해결실전! Querydsl
persist 에 unknown Entity Hello 에러
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]안녕하세요, Hello hello = new Hello();em.persist(hello); 여기서 persist 에 unknown Entity Hello 하고 에러가 뜨는데요 최신 버전의 스프링부트를 다운받아 그레들 버전도 7이라서 버전의 문제인가 검색을 통해 해결하려고 했지만 잘안되어서 질문을 남기게 되었습니다. 구글드라이브에 파일을 업로드하였는데 한 번 봐주셨으면 합니다. https://drive.google.com/file/d/1JN665qqgZ2DqhBJW5XIWCyiXcBWp0Yze/view?usp=sharing
- 미해결실전! Querydsl
concat() stringValue 나이를 완전히 가져오지 못합니다.ㅠㅠ
안녕하세요 질문이 있습니다 concat을 사용해서 stringValue를 활용할 때 나이를 다 가져오지 못하고 맨 앞에 있는 숫자만 가져오는데 왜 그럴까요ㅠㅠㅠㅠ
- 미해결실전! Querydsl
서브쿼리와 dto에 대해서 물어볼게 있습니다.
안녕하세요 제가 querydsl로 프로젝트를 하는 중인데 queryFactory .select(new QDto(user.id, JPAExpressions. 서브쿼리문) ) 이렇게 Dto 안에 서브쿼리문이 들어갈 수 있나요? 아무리 작업을 해도 안되서 물어봅니다ㅠㅠ
- 미해결실전! Querydsl
단축키 문의
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]영한님 강의하시다 보면 intellij 상에서 함수를 선택한 후에 단축키를 누르면, 리턴 타입과 리턴 변수가 자동 생성되던데, 해당 단축키좀 알수 있을까요?
- 미해결실전! Querydsl
영속성 컨텍스트에 대해 질문드립니다.
jpaQueryFactory .selectFrom(member) .fetch();jpaQueryFactory .selectFrom(member) .fetch();이런식으로 테스트 코드를 짠 후 실행시켰는데select문이 2번 나갔습니다.제가 이해한 바로는 select문이 한번 나가고 2번째 쿼리에 대해서는 영속성 컨텍스트 1차 캐시에서 가져와서select문이 안나가야 하는데2번 나간게 이해가 되질 않습니다..
- 미해결실전! Querydsl
queryDsl 페치 조인 질문드립니다.
Member findMember = jpaQueryFactory .selectFrom(QMember.member) .join(member.team, team).fetchJoin()//뒤에 fetchJoin만 붙여주면 된다. .where(QMember.member.username.eq("member1")) .fetchOne(); jpaQueryFactory .select(QMember.member, team) .from(member) .join(member.team, team) .where(QMember.member.username.eq("member1")) .fetchOne();첫번째건 fetchjoin을 사용한 것이고두번째건 select(member, team) 하고 join 한 것인데jqpl은 다르게 나가더라도 결국 sql 은 같게 나옵니다.차이가 없는건가요?
- 미해결실전! Querydsl
안녕하세요 마지막 applyPagination 구현시 stackOverFlow 에러 질문 드려요..
@GetMapping("/v5/members")public Page<Member> searchMemberV5ByCustomSupport(MemberSearchCondition condition, Pageable pageable) { return memberTestRepositoryBySupport.applyPagination(condition, pageable);} 다름 아니라 테스트 겸 해당 컨트롤러를 만들어서 호출해보니 스택오버 플로우 발생되어 질문 올려요. Member 엔티티쪽에는 Lazy 설정 해놨구, // return applyPagination(pageable, query -> query// .selectFrom(member)// .leftJoin(member.team, team)// .where(// usernameEq(condition.getUsername()),// teamNameEq(condition.getTeamName()),// ageGoe(condition.getAgeGoe()),// ageLoe(condition.getAgeLoe())// )// ); return applyPagination(pageable, query -> query .selectFrom(member) .leftJoin(member.team, team) .fetchJoin() .distinct() .where( usernameEq(condition.getUsername()), teamNameEq(condition.getTeamName()), ageGoe(condition.getAgeGoe()), ageLoe(condition.getAgeLoe()) ) ); } 주석부분은 영한님이 적으신 거고 아래쪽은 제가 해결해 보려 적은 코드 부분입니다. 질문은 2가지로써.. 1.결과적으로 JsonIgnore 적용하면 값은 제대로 나오는데 JsonIgnore 말고는 방법이 없을까요?? 2.영한님이 제공해 주신 dsl4Repository 애서 PageableExcutionUtils 는 더이상 지원이 안되는 것 처럼 줄이 그어져 있는데 다른 방법이 있을까요? 읽어 주셔서 감사합니다. 강의는 정말 돈이 전혀 아깝지 않을 정도로 훌륭하더군요!!:) 추가 : return applyPagination(pageable, query -> query .select(new QMemberTeamDto( member.id, member.username, member.age, team.id, team.name)) .from(member) .leftJoin(member.team, team) .where( usernameEq(condition.getUsername()), teamNameEq(condition.getTeamName()), ageGoe(condition.getAgeGoe()), ageLoe(condition.getAgeLoe()) )); 해당 return 타입을 dto로 변경하고 JsonIgnore 삭제하면 페이지는 잘 나옵니다.. entity 로 가져와서 dto를 반환하는게 나을까요..바로 dto로 조회하는게 나을런지요.. 제 생각에는 dto로 변환하는게 로직을 한번 이라도 덜 태워서 나을것 같긴한데..고견을...말씀해 주시면 감사하겠습니다ㅜㅜ 혹 Entity로 가져와서 dto 로 변환해야 한다면, 알려주신 방법처럼 Stream() 을 이용한 map()형식의 리스트로 변환하는게 좋을까요??성능에 문제가 없을지 궁금하기도한데.. 질문이 많쵸..부족함이 많아서 그런거 같습니다.. 감사합니다!
- 미해결실전! Querydsl
영한님..안녕하세요..page total count 질문있어요 ㅠㅠ
영한님 안녕하세요 강의 정말 좋아요!! 다름아니라 질문이 있어서 남겨봐요... totalCount를 구하려할때 SearchSimple 같은경우 content를 가져와서 fetch()를 쓰는데용..(fetchResults)가 사용이 안되어서요.. content 로 값을 가져와서 content.size()를 하면 토탈 카운트가 안뽑히던데..혹시 total count 를 뽑느 예시가 있을까요?? 새벽이라 너무 졸려서 질문이 이상한 점 죄송해요 혹시 질문이 이해가 잘 안되시면 답변주시면, 제가 다시 올려보겠습니다 ㅠㅠ.. 코드를 복사하려해도 지금 다른 컴퓨터 2대로 보고있어서 힘들어서요 ㅠㅠ.. 감사합니다
- 미해결실전! Querydsl
안녕하세요 프로젝션 결과반환을 dto로 하는데 있어 질문을 드립니다
안녕하세요 현재 jpa 모든 강의를 듣고 토이프로젝트를 진행하고 있습니다 질문의 요지는 querydsl을 통해 dto로 조회할때 XXXtoMany 관계의 컬렉션을 함께 조회하고 싶어요 현재 제 상황은 이렇습니다 일기장에 일기를 쓰는데 질문을 통해 일기를 쓰는방식이라 일기장에 사용된 질문이 필요해요 Diary라는 엔티티가 있고 Question이라는 엔티티가 있는데 이 두 엔티티의 관계가 다대다 관계여서 가운데 DiaryItem이라는 엔티티를 두고 다이어리 페이지에 필요한 모든 정보를 한번에 조회하는것이 목적입니다 이런 방식으로 Diary엔티티를 조회할때와 마찬가지로 엔티티에 의존적이지 않게 dto로 받으면서 무한루프에 빠지지 않도록 필요한 정보만 받을 수 있도록 조회를 하는 방법이 궁금해 질문드립니다 같은 방식으로 DiaryDto가 아니라 Diary에 담은뒤 Controller에서 DiaryDto의 생성자를 통해 변환을 하면 정상적으로 값이 담겨 오는데 queryFactory의 fetch를 통해 직접 DiaryDto에 담으면 에러가 발생합니다ㅠㅠ 현재 이방식으로 쿼리를 실행해보면 query specified join fetching, but the owner of the fetched association was not present in the select list 라는 에러가 나옵니다... 어떤에러인지도 궁금하구요ㅠㅠ 도움부탁드립니다ㅎㅎ
- 미해결실전! Querydsl
querydsl 쿼리 테스트 작성이 궁금합니다.
과 같이 구성했을 때 queryDSL 의 쿼리의 테스트코드를 작성할 때 springboottest 로 올려야할까요? memberRepository 는 interface니까 순수 JUnit 테스트로 하려니 객체를 생성할 수가 없어서 스프링부트테스트로 올려서 빈으로 받아오는 방법말곤 잘 모르겠습니다. (찾다보니 querydsl 자체를 jpaqueryfactory 를 mocking 해서 테스트하는게 있긴하던데 쿼리가 동작하는지 확인하는데 모킹으로 테스트하는 건 기능이 잘 작동하는지 보장하지 않는다고 생각합니다) 혹시 queryDSL 의 테스트를 작성해야 한다면 어떻게 해야할까요?
- 미해결실전! Querydsl
페치조인 질문입니다.
안녕하세요 개인프로젝트를 하다가 궁금한게 생겨서 질문드립니다! 궁금한 것은 페치조인시 조인할 엔티티의 전부가 아닌 일부분만 조인할 수 있나? 입니다. 일반적으로 페치조인을 사용하면 팀(영상기준) 엔티티의 전부가 조인되는데 만약 팀 엔티티의 name만 사용하고 싶을때 그부분만 패치조인을 사용할 수 있을까요? java QueryResults<Recipe> recipeQueryResults = queryFactory .selectFrom(recipe) .join(recipe.member, member).fetchJoin() .offset(page*10) .limit(pageable.getPageSize()) .fetchResults(); Hibernate Hibernate: select recipe0_.recipe_id as recipe_i1_2_0_, member1_.member_id as member_i1_1_1_, recipe0_.created_date as created_2_2_0_, recipe0_.modified_date as modified3_2_0_, recipe0_.content as content4_2_0_, recipe0_.member_id as member_i6_2_0_, recipe0_.title as title5_2_0_, member1_.created_date as created_2_1_1_, member1_.modified_date as modified3_1_1_, member1_.email as email4_1_1_, member1_.name as name5_1_1_, member1_.password as password6_1_1_, member1_.role as role7_1_1_, member1_.user_id as user_id8_1_1_ from recipe recipe0_ inner join member member1_ on recipe0_.member_id=member1_.member_id 혹시나 제 설명이 이상할까봐 덧붙입니다.. 예를 들어서 위 코드에서는 member의 전부를 페치조인하지만 만약 member의 name만 페치조인 할 수 있는지에 대한 질문입니다.
- 미해결실전! Querydsl
fetchresults, fetchcount 공식적 deprecated
안녕하세요. 강의 잘 듣고 있습니다. querydsl 개발진 측에서 fetchCount와 groupby를 함께 사용할 때 생기는 문제로 인해 fetchcount 함수를 deprecated 시켰습니다.그런데 영한님 강의 중 querySupportReposity 사용자 정의 구현 클래스에서도 이 deprecated된 메서드를 사용하고 있습니다. 그래서 그것의 대안으로 fetch().size()를 제안하고 있는데, 그래서 제 나름대로 fetchCount 부분을 아래처럼 변경했습니다. protected <T> Page<T> applyPagination(Pageable pageable, Function<JPAQueryFactory, JPAQuery> contentQuery) { JPAQuery jpaQuery = contentQuery.apply(getQueryFactory()); List<T> content = getQuerydsl().applyPagination(pageable, jpaQuery).fetch(); return PageableExecutionUtils.getPage(content, pageable, () -> Long.valueOf(jpaQuery.fetch().size()));}protected <T> Page<T> applyPagination(Pageable pageable, Function<JPAQueryFactory, JPAQuery> contentQuery, Function<JPAQueryFactory, JPAQuery> countQuery) { JPAQuery jpaContentQuery = contentQuery.apply(getQueryFactory()); List<T> content = getQuerydsl().applyPagination(pageable, jpaContentQuery).fetch(); JPAQuery countResult = countQuery.apply(getQueryFactory()); return PageableExecutionUtils.getPage(content, pageable, () -> Long.valueOf(countResult.fetch().size()));} 그러나 이것은 List의 size를 추출하는 거라서 int를 반환하게 되는데, 만약 조회개수가 int 범위를 넘어가게 되면 오버플로우 문제가 발생할텐데 다른 해결 방법이 있을까요?제 생각엔 아래의 2가지 방법만 있다고 생각하는데, querydsl을 그대로 사용하면서 다른 방법이 있을까요?1.스프링데이터JPA 구현 repository를 만들어 순수 JPA 쿼리로 사용하기 public long totalCount(int age) { return em.createQuery("select count(m) from Member m where m.age = :age", Long.class) .setParameter("age", age) .getSingleResult();} 2. native query 사용하기
- 미해결실전! Querydsl
QueryDSL collection 다루기 질문있습니다.
List<String> permissionList = Arrays.asList("CONTENT_READ", "CONTENT_WRITE"); User --- UserPermission --- Permissions로 각각 one to many ,many to one 으로 이루어져있는데 퍼미션들을 하나라도 가지고 있는 유저를 뽑을 땐 qf.selectFrom(user).innerJoin(user.userPermissions, permission).on(user.permissions.`in`(permissionList)) 이렇게 할 수 있는 것 같은데 다 가지고 있는 유저를 선택할 땐 어떻게 해야할까요?
- 미해결실전! Querydsl
from 절의 subquery와 view 테이블 관련
안녕하세요, 김영한님 강의 잘 듣고있습니다! 혹시 from 절에 subquery를 사용하게 되는 경우 JPA에서는 한계가 있다면 View 테이블을 만들어 놓고 Entity class를 생성하여 사용하는건 실무에서 문제가 있을까요? (유지보수 관점에서요!) select * from (select ~~~ from ~~) ~~ 이거를 create view XXX as select ~~~ from ~~ view 를 만들어놓고 select * from XXX; 요렇게요 답변 미리 감사합니다 :)
- 미해결실전! Querydsl
MyBatis vs JPA vs JPA + querydsl 질문이 있습니다.
JPA(ORM) 장점 1) RDB에 종류와 관계없이 사용 가능하다. 추후 DB 변경이나 코드 재활용에 용이하다. 2) 비지니스 로직에 집중할 수 있다. 3) 테이블 생성, 변경 등 엔티티 관리가 간편하다. 4) 쿼리에 집중할 필요 없어 빠른 개발이 가능하다. 단점 1) 어렵다. 단방향, 양방향, 임베디드 관계 등 이해해야할 내용이 많으며, MyBatis(SQL Mapper) 장점 1) JPA에 비해 쉽다. SQL 쿼리를 그대로 사용하기에 복잡한 Join, 튜닝 등을 좀더 수월하게 작성 가능하다. 2) SQL의 세부적인 내용 변경 시 좀 더 간편하다. 3) 동적 쿼리 사용 시 JPA보다 간편하게 구현 가능하다. 단점 1) 데이터 베이스 설정 변경 시 수정할 부분이 너무 많다. (Oracle의 페이징 쿼리를 MySQL에서 사용 불가능!) 2) Mapper작성부터 인터페이스 설계까지 JPA보다 많은 설계와 파일, 로직이 필요하다. 3) 특정 DB에 종속적이다. Querydsl 장점 1) 쿼리를 자바 코드로 작성 2) 문법 오류를 컴파일 시점에 잡을 수 있음. 3) 쉬운 SQL 스타일 문법(복잡한 쿼리 작성 용이) 질문 : Querydsl 초반부만 듣고 있는 수강생입니다. 1) 서비스가 MVC + MYBatis에서 JPA + querydsl 바꾸는 점에 있어 생기는 기본적인 문제들이 있을까요? 2) QueryDSL이 MyBatis를 대신해 커버 가능할까요?
- 미해결실전! Querydsl
querydsl 스프링부트에 적용시 질문이 있습니다
빌드된 파일이 있을 경우엔 상관이 없지만 ./gradlew clean 을 돌려서 빌드파일을 모두 삭제하고나서 어플리케이션을 실행하면 QMember 를 찾을 수 없어서 실행이 되지 않습니다. 저는 클린했다가 어플리케이션 run만 돌려도 실행이 가능해야 한다고 생각합니다. 그냥 빌드돌리고 run 하도록 하는게 맞을까요?
- 미해결실전! Querydsl
fetchCount @Deprecated
안녕하세요 영한님 2:10분 쯤 @Deprecated 이 되었는데 이렇게 쓰면 될까요 ??
- 해결됨실전! Querydsl
select()가 아닌 selectOne()을 사용하면 fetchJoin을 사용하지 못하나요?
안녕하세요. 강의 잘 듣고 있습니다 :) exists 기능을 구현하고 있는데, fetchJoin을 사용해봤습니다. 그저 데이터의 유무만 판단하면 됐기에 selectOne() 으로 조회를 했는데 실패하네요 ㅠㅠ 하지만 이후 fetchJoin()을 제거하니 잘 동작하는 모습을 확인했습니다. // 성공하는 코드 @Override public boolean existsByReviewEntity(ReviewEntity reviewCond) { final Integer result = queryFactory .selectOne() .from(reviewCommentEntity) .innerJoin(reviewCommentEntity.reviewEntity, reviewEntity) .where(reviewEq(reviewCond)) .fetchFirst(); return result != null; } // 실패하는 코드 @Override public boolean existsByReviewEntity(ReviewEntity reviewCond) { final Integer result = queryFactory .selectOne() .from(reviewCommentEntity) .innerJoin(reviewCommentEntity.reviewEntity, reviewEntity).fetchJoin() .where(reviewEq(reviewCond)) .fetchFirst(); return result != null; } 제 생각에는 두 가지 이유가 추측되는데요, 1. selectOne 이랑 fetchJoin의 실행 순서(?) 2. select 1 을 하면 특정 필드를 가져오는 것이 아니기 때문에 fetchJoin이 불가능(?) 열심히 구글을 찾아봐도 만족스러운 답을 찾지 못했고, 두루뭉실하게 의문만 남아있는 상태네요.. 도움 주시면 감사하겠습니다 !! 짤막한 힌트도 좋습니다 :)
- 미해결실전! Querydsl
querydsl 동적 쿼리 질문
안녕하세요 영한님! 강의는 잘 듣고 있습니다. 강의를 듣다가 궁금한 점이 어디까지 동적쿼리로 생성할 수 있는가 하는 부분이었습니다. 구체적으로는 특정 조건에서는 join 을 실행하고 아니면 join 을 실행하지 않게 만들 수 있을까요? join 하는 테이블을 명시해야할텐데 그럼 테이블을 명시하고 on 이나 where 로 처리가 가능할지 궁금합니다 두 번째로는 where 절로 쿼리 파라미터를 BooleanBuilder 등을 통해서 쓸 수 있는데 join 의 on 절에 where 에 쓰던 방식 그대로 적용해도 되는지가 궁금합니다.(예외상황이 없는지) 감사합니다