📃 요약
실무에서는 MVC 디자인 패턴 속해서 스프링부트를 사용해 코딩을 진행함. 파일관리 시 파일을 용도에 맞게 정리하듯이 MVC 디자인 패턴도 패키지 및 클래스를 용도에 맞게 분류해서 코딩을 진행함
요소 기술 :
– Basic : java & spring boot
📃 기술 구현
스펙 :
- intellij - java - spring boot
📃 Querydsl :
- DB 에 접속하여 CRUD를 실행하는 라이브러리 - sql 문을 작성하는 것이 아니라 sql 문의 키워드에 해당하는 함수를 메소드 체이닝을 이용해서 작성하는 방식 - 다이나믹 쿼리 작성해야 할때 Querydsl 를 많이 사용함 - 원본 클래스를 사용하지 않고, 복사본(Q클래스) 을 사용해서 실행함 - 때에 따라서 JPA 기본 함수외에 직접 sql 문을 작성해야 할때가 있음. 이때 JPQL 를 사용하지 않고 Querydsl 로 대체해서 사용하는 회사도 있음(배달의 민족 등)
build.gradle
plugins { id 'java' id 'war' id 'org.springframework.boot' version '2.7.11' id 'io.spring.dependency-management' version '1.0.15.RELEASE' // TODO: 1) querydsl 추가 id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { ... // TODO: 2) querydsl 추가 implementation "com.querydsl:querydsl-jpa:5.0.0" annotationProcessor "com.querydsl:querydsl-apt:5.0.0" ... } tasks.named('test') { useJUnitPlatform() } // TODO: 3) 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 }
QuerydslConfig.java
- config 폴더를 만들어서 추가함 - Querydsl 과 JPA 를 연결하는 설정 파일 1) JPAQueryFactory 객체에 JPA 객체를 넣어서 연동시킴 2) Querydsl 사용시 다른 자바 파일에서 JPAQueryFactory 객체를 생성하면 사용할 수 있음
package com.example.jpaquerydslexam.config; import com.querydsl.jpa.impl.JPAQueryFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; @Configuration public class QuerydslConfig { @PersistenceContext private EntityManager entityManager; @Bean public JPAQueryFactory jpaQueryFactory() { return new JPAQueryFactory(entityManager); } }
querydsl 클래스 : 조회
- 사용할 함수를 미리 정의해 놓은 클래스 - 여기서 직접 SQL 문을 작성할 수 있음 : 체이닝 함수를 연결해 쿼리문 작성함 - 예 : 1) select -> select() 함수 2) from -> from() 함수 3) where -> where() 함수 4) order by -> orderBy() 함수 ... - JPAQueryFactory @Audowired 로 DI 함 - 엔티티 복사본 Q 클래스를 생성해서 사용함
사용법 : @Repository public class 클래스명 { @Autowired private JPAQueryFactory queryFactory; // querydsl DI private Q클래스명 객체명 = Q클래스명.객체명; // 복사본 Q 클래스 public List<엔티티명> 함수명(변수명) { List<엔티티명> list = queryFactory .selectFrom(객체명) .where( 객체명.속성명.contains(매개변수명) ) .fetch(); // 조회 실행 return list; } ... } 예 : @Repository public class 클래스명 { @Autowired private JPAQueryFactory queryFactory; // querydsl DI private QDept dept = QDept.dept; // 복사본 Q 클래스 // 1) dname 으로 like 검색 public List<Dept> querydslByDname(String dname) { List<Dept> list = queryFactory .selectFrom(dept) .where( dept.dname.contains(dname) ) .fetch(); // 조회 실행 return list; } }
querydsl 클래스 : 페이징 처리
- 사용할 함수를 미리 정의해 놓은 클래스 - 여기서 직접 SQL 문을 작성할 수 있음 : 체이닝 함수를 연결해 쿼리문 작성함 - 예 : 1) select -> select() 함수 2) from -> from() 함수 3) where -> where() 함수 4) order by -> orderBy() 함수 ... - JPAQueryFactory @Audowired 로 DI 함 - 엔티티 복사본 Q 클래스를 생성해서 사용함 - PageImpl<>(결과객체, pageable, 전체카운트) : 객체를 이용해 페이징처리함
querydsl 클래스 / 함수
사용법 : @Repository public class 클래스명 { @Autowired private JPAQueryFactory queryFactory; // querydsl DI private Q클래스명 객체명 = Q클래스명.객체명; // 복사본 Q 클래스 public List<엔티티명> 함수명(변수명) { List<엔티티명> list = queryFactory .selectFrom(객체명) .where( 객체명.속성명.contains(매개변수명) ) .fetch(); // 조회 실행 Long count = queryFactory .select(객체명.count()) .from(객체명) .where( 객체명.속성명.contains(매개변수명) ) .fetch(); // 조회 실행 // PageImpl<>(결과객체, pageable, 전체카운트) return new PageImpl<>(list, pageable, count); } ... } 예 : @Repository public class 클래스명 { @Autowired private JPAQueryFactory queryFactory; // querydsl DI private QDept dept = QDept.dept; // 복사본 Q 클래스 // 1) dname 으로 like 검색 public Page<Dept> querydslByDname(String dname) { List<Dept> list = queryFactory .selectFrom(dept) .where( dept.dname.contains(dname) ) .fetch(); // 조회 실행 Long count = queryFactory .select(dept.count()) .from(dept) .where( dept.dname.contains(dname) ) .fetchOne(); // 조회 실행 // PageImpl<>(결과객체, pageable, 전체카운트) return new PageImpl<>(list, pageable, count); } }
querydsl 클래스 : 다이나믹 쿼리
- 다이나믹 쿼리 : 조건의 형태가 매개변수의 값에 따라 달라지는 것 - JPQL 에서는 사용하기 어려우나 querydsl 은 간단하게 사용할 수 있게 지원함
querydsl 클래스 / 함수
사용법 : @Repository public class 클래스명 { @Autowired private JPAQueryFactory queryFactory; // querydsl DI private Q클래스명 객체명 = Q클래스명.객체명; // 복사본 Q 클래스 // 동적 쿼리 : ename or job public List<객체명> 함수명(String 변수명, String 변수명2) { BooleanBuilder builder = new BooleanBuilder(); if (변수명 != null) { builder.and(객체명.속성명.contains(변수명)); } if (변수명2 != null) { builder.and(객체명.속성명.contains(변수명)); } return queryFactory .selectFrom(객체명) .where(builder) // 위에서 만든 동적으로 만들어 지는 where 절 추가 .fetch(); // 조회 실행 } ... } 예 : @Repository public class DeptRepositoryDsl { @Autowired private JPAQueryFactory queryFactory; // querydsl DI private QEmp emp = QEmp.emp; // 복사본 Q 클래스 public List<Dept> querydslByDynamicName(String dname, String loc) { BooleanBuilder builder = new BooleanBuilder(); // dname 이 null 이 아니면 where dname like '%dname%' 추가 if (dname != null) { builder.and(dept.dname.contains(dname)); } // loc 이 null 이 아니면 where loc like '%loc%' 추가 if (loc != null) { builder.and(dept.loc.contains(loc)); } return queryFactory .selectFrom(dept) .where(builder) // 위에서 만든 동적으로 만들어 지는 where 절 추가 .fetch(); // 조회 실행 } }