커리큘럼(12-30/변경)
01. Java
02. git
03. Database
04. Jsp [Server]
05. HTML,CSS
07. JS
06. 미니프로젝트-2W
08. SpringFramework , SrpingBoot (v)
09. React JS [Front-end]
10. 중간프로젝트 (1M)
11. Linux 명령어
12. AWS 클라우드
13. DevOps - Docker
14. App - Android
15. 최종프로젝트 (1M)
스프링 부트
쿼리 DSL
- 하이버네이트 쿼리언어(HQL:Hibernate Query Language)의 쿼리를 타입에 안전하게 생성 및 관리해주는 프레임워크
- JPQL문을 문자열이 아닌 자바코드로 작성할 수 있도록 도와줌
장점
- 문법 오류를 컴파일 단계에서 발견 가능
- 쿼리를 Java코드로 표현하므로 가독성이 좋고, 복잡한 쿼리도 더 명확하게 작성할 수 있음
- 동적 쿼리 작성이 용이함(검색 조건절)
쿼리DSL 개발설정
//1. 쿼리DSL
buildscript {
ext {
queryDslVersion = "5.0.0"
}
}
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.18'
id 'io.spring.dependency-management' version '1.1.5'
id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10' //2. 쿼리DSL 버전
}
//기본 내용 생략.........
dependencies {
//생략....
//3. 쿼리DSL 의존성
implementation "com.querydsl:querydsl-jpa:${queryDslVersion}"
implementation "com.querydsl:querydsl-apt:${queryDslVersion}"
}
///////////////4. 빌드시 테스트코드를 모두 실행하는데, 테스트 코드는 빌드 제외//////////////
tasks.withType(Test) {
enabled = false
}
///////////////5. 쿼리DSL Q클래스 위치지정////////////////
def querydslDir = "$buildDir/generated/querydsl"
querydsl {
jpa = true
querydslSourcesDir = querydslDir
}
sourceSets {
main.java.srcDir querydslDir
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
querydsl.extendsFrom compileClasspath
}
compileQuerydsl {
options.annotationProcessorPath = configurations.querydsl
}
////////////////////////////////////////
- 이클립스 상단 메뉴에서 window 클릭
- Show View -> other -> gradle 검색 -> Gradle Task 클릭
- Gradle Task에서 해당 프로젝트를 더블클릭
- build 폴더로 가서 build를 선택 후 마우스 오른쪽 클릭
- Run Gradle Tasks를 클릭하면 src밑에 generated 폴더가 생성
- build.gradle 그레이들업데이트 (F5로 확인)
- Q로시작되는 클래스는 개발자가 직접 건드리는 클래스가 아니라 그레이들task를 통해 자동으로 생성되는 클래스만사용
- @Entity 클래스마다 Q~ 클래스가 생성되고 해당 Q~ 클래스와 JPAQueryFactory를 사용하여 JPQL을 생성하고 실행
- 추가적인 클래스 상속 (반드시 필수는 아니지만 추가하면 좋음)
- QuerydslPredicateExecutor인터페이스는
JPA의 기본 함수
를 사용할때 동적쿼리를 제공하도록 지원합니다.
- 메서드의 인자로 Predicate 타입을 직접 넘겨 주는 데, 이는 querydsl의 조건문을 작성할 수 있게 도와줍니다
//인터페이스의 추상메서드들
public interface QuerydslPredicateExecutor<T> {
Optional<T> findById(Predicate predicate);
Iterable<T> findAll(Predicate predicate);
long count(Predicate predicate);
boolean exists(Predicate predicate);
}
- XXXCustomRepository에 메서드를 선언하고 XXXCustomRepositoryImpl 에는 JPAQueryFactory를 주입받음
- 다음과 같은 요소들이 필수적으로 필요
- 생성자를 통해 entityManager를 받고, 매개변수에 저장
- 객체가 생성되는 순서때문에 반드시 아래와 같이 처리
public class MemoCustomRepositoryImpl implements MemoCustomRepository {
//커스텀Repository
@PersistenceContext //퍼시트턴스매니저를 주입받을 때 사용합니다.
private EntityManager entityManager;
//쿼리DSL
private JPAQueryFactory jpaQueryFactory;
public MemoCustomRepositoryImpl(EntityManager entityManager) {
this.jpaQueryFactory = new JPAQueryFactory(entityManager);
}
//구현체 메서드 작성
}
쿼리DSL 기본문법
@Override
public Memo dslSelect() {
//Q클래스를 사용함
QMemo memo = QMemo.memo;
Memo m = jpaQueryFactory.select(memo) //Q클래스
.from(memo) //Q클래스
.where(memo.mno.eq(10L) ) //Q클래스 멤버변수로 조건
.orderBy(memo.text.desc()) //차순정렬
.fetchOne(); //fetchOne() 1행 조회, fetch() 리스트 조회, execute() 는 인서트, 업데이트, 딜리트
return m;
}
//DSL여러행
@Override
public List<Memo> dslSelect2() {
//Q클래스를 사용함
QMemo memo = QMemo.memo;
List<Memo> m = jpaQueryFactory.select(memo) //메모엔티티 컬럼을
.from(memo) //메모엔티티 에서
//.where(memo.text.like("%2%")) //where text like '%2%'
//.where(memo.mno.gt(10).and(memo.mno.lt(20) )) //where mno > 10 and mno < 20
.where(memo.mno.goe(10).and(memo.mno.loe(20) )) //where mno >= 10 and mno <= 20
.fetch(); //fetchOne() 1행 조회, fetch() 리스트 조회, execute() 는 인서트, 업데이트, 딜리트
return m;
}
@Override
public List<Memo> selectDsl3(String searchType, String searchName) {
QMemo memo = QMemo.memo;
BooleanBuilder builder = new BooleanBuilder();
if(searchType!=null && searchType.equals("writer")){
builder.and(memo.writer.like("%"+searchName+"%"));
}
if(searchType!=null && searchType.equals("text")){
builder.and(memo.text.like("%"+searchName+"%"));
}
List<Memo> list = jpaQueryFactory.select(memo)
.from(memo)
.where(builder)
.fetch();
return list;
}