
📃 요약
실무에서는 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(); // 조회 실행
}
}



