Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 벌크 연산
- 트위터
- 김영한
- 불변 객체
- 스프링MVC
- 스프링
- 임베디드 타입
- 기본문법
- 스프링 데이터 JPA
- jpa 활용
- Spring Data JPA
- 페이징
- JPA
- QueryDSL
- 타임리프 문법
- 로그인
- JPQL
- 타임리프
- 값 타입 컬렉션
- 검증 애노테이션
- 컬렉션 조회 최적화
- JPA 활용2
- JPA 활용 2
- 예제 도메인 모델
- 스프링 mvc
- Bean Validation
- 일론머스크
- API 개발 고급
- 프로젝트 환경설정
- 실무활용
Archives
- Today
- Total
RE-Heat 개발자 일지
[JPA 활용2] [6] 스프링 데이터 JPA·Querydsl 소개 본문
인프런 김영한 님의 강의를 듣고 작성한 글입니다.
[1] 스프링 데이터 JPA 소개
스프링 데이터 JPA는 JPA를 사용할 때 지루하게 반복되는 코드를 자동화해 준다.
MemberRepositoryOld - 스프링 데이터 적용 전
@Repository
@RequiredArgsConstructor
public class MemberRepositoryOld {
private final EntityManager em;
public void save(Member member) {
em.persist(member);
}
public Member findOne(Long id) {
return em.find(Member.class, id);
}
public List<Member> findAll() {
return em.createQuery("select m from Member m", Member.class) //JPQL from의 대상이 엔티티라는 게 좀 다름
.getResultList();
}
public List<Member> findByName(String name) {
return em.createQuery("select m From Member m where m.name= :name", Member.class)
.setParameter("name", name)
.getResultList();
}
}
MemberRepository - 스프링 데이터 적용 후
public interface MemberRepository extends JpaRepository<Member, Long> {
//select m from Member m where m.name = ?
List<Member> findByName(String name);
}
- 인터페이스로 만들고 JpaRepository를 상속한다.
- JpaRepository<>라는 인터페이스는 기본적인 CRUD 기능을 제공한다.
- save, findById 등 생각할 수 있는 다양한 기능을 제공한다.
- 공통이 아닌 findByName()도 따로 넣어주면 where 조건에 name이 자동으로 들어간다.
- 개발자는 인터페이스만 만들면 구현체는 스프링 데이터 JPA가 애플리케이션 실행시점에 주입해 준다.
[2] Querydsl 소개
Querydsl은 SQL(JPQL)과 모양이 유사하며 자바 코드로 동적 쿼리를 편리하게 생성할 수 있다.
■ Querydsl 적용 전 기존 동적쿼리
① 문자로 만든 동적 쿼리
- 띄어쓰기 실수라도 하면 오류가 뜬다.
② JPA Criteria
- 어떤 JPQL이 날아갈지 생각해 내기 쉽지 않다.
■ Querydsl 적용
① 세팅 방법
build.gradle 수정
//querydsl 추가
buildscript {
dependencies {
classpath("gradle.plugin.com.ewerk.gradle.plugins:querydsl-plugin:1.0.10")
}
}
plugins {
id 'org.springframework.boot' version '2.4.1'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
}
group = 'jpabook'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
//apply plugin: 'io.spring.dependency-management'
apply plugin: "com.ewerk.gradle.plugins.querydsl"
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-devtools'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5'
// implementation 'org.hibernate:hibernate-core:5.4.13.Final'
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.6'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
//추가
testImplementation("org.junit.vintage:junit-vintage-engine") {
exclude group: "org.hamcrest", module: "hamcrest-core"
}
//querydsl 추가
implementation 'com.querydsl:querydsl-jpa'
//querydsl 추가
implementation 'com.querydsl:querydsl-apt'
}
//querydsl 추가
//def querydslDir = 'src/main/generated'
def querydslDir = "$buildDir/generated/querydsl"
querydsl {
library = "com.querydsl:querydsl-apt"
jpa = true
querydslSourcesDir = querydslDir
}
sourceSets {
main {
java {
srcDirs = ['src/main/java', querydslDir]
}
}
}
compileQuerydsl{
options.annotationProcessorPath = configurations.querydsl
}
configurations {
querydsl.extendsFrom compileClasspath
}
- generated된 Q파일이 어디에 위치할지 명시하는 등 세팅 작업이 조금 복잡한 편이다.
② Querydsl 적용 동적 쿼리
public List<Order> findAll(OrderSearch orderSearch) {
QOrder order = QOrder.order;
QMember member = QMember.member;
JPAQueryFactory query = new JPAQueryFactory(em)
return query
.select(order)
.from(order)
.join(order.member, member)
.where(statusEq(orderSearch.getOrderStatus()),
nameLike(orderSearch.getMemberName()))
.limit(1000)
.fetch();
}
private BooleanExpression statusEq(OrderStatus statusCond) {
if (statusCond == null) {
return null;
}
return order.status.eq(statusCond);
}
private BooleanExpression nameLike(String nameCond) {
if (!StringUtils.hasText(nameCond)) {
return null;
}
return member.name.like(nameCond);
}
- QOrder, QMember는 static화, JPAQueryFactory는 생성자 주입 방식으로 처리 가능
■ Querydsl 장점
- 직관적인 문법
- 컴파일 시점에 빠른 문법 오류 발견 : 자바 코드여서 가능함
- 코드 자동완성 : 자바코드여서 IntelliJ에서 자동완성 기능 제공
- 코드 재사용 : statusEq 등 재사용 가능한 데 역시 자바 코드여서 가능한 일이다.
- JPQL new 명령어와는 비교는 안될 정도로 깔끔한 DTO 조회를 지원한다.
'백엔드 > JPA' 카테고리의 다른 글
[JPA 활용2] [5] API 개발 고급 - 실무 필수 최적화 (0) | 2023.09.06 |
---|---|
[JPA 활용2] [4] API 개발 고급 - 컬렉션 조회 최적화(하편) (0) | 2023.09.03 |
[JPA 활용2] [4] API 개발 고급 - 컬렉션 조회 최적화(상편) (0) | 2023.09.01 |
[JPA 활용2] [3] API 개발 고급 - 지연 로딩과 조회 성능 최적화 (0) | 2023.08.31 |
[JPA 활용2] [2] API 개발 고급 - 준비 (0) | 2023.08.31 |