JPA
JPA 기본기 다지기 Spring Data JPA와 QueryDSL
JANNNNNN
2024. 3. 27. 11:16
- 지루하게 반복, 중복되는 CRUD 문제를 세련된 방법으로 해결
- 개발자는 인터페이스만 작성
- 스프링 데이터 JPA가 구현 객체를 동적으로 생성해서 주입
적용 전
public class MemberRepository {
public void save(Member member) {...}
public Member findById(Long id) {...}
public List<Member> findAll() {...}
public Member findByUsername() {...}
}
적용 후
public interface MemberRepsoitory extends JpaRepository<Member, Long> {
List<Member> findByUsername(String username)
}
적용 후 다이어그램
구현 클래스 생성
공통 인터페이스 기능
public interface MemberRepsoitory extends JpaRepository<Member, Long> {
Member findByUsername()
}
- JpaRepository 인터페이스 : 공통 CRUD 제공
- 제네릭은 <엔티티, 식별자>로 설정
메서드 이름만으로 JPQL 쿼리 생성
public interface MemberRepsoitory extends JpaRepository<Member, Long> {
List<Member> findByUsername(String username); // 검색
List<member> findByUsername(String username, Sort sort); // 검색 + 정렬
List<Member> findByUsername(String username, Pageable Pagealbe); // 검색 + 정렬 + 페이징
}
@Query, JPQL 정리
public interface MemberRepsoitory extends JpaRepository<Member, Long> {
@Query("SELECT m FROM Member m WHERE m.username = ?1")
List<Member> findByUsername(String username);
}
Web 페이징과 정렬기능
Web 도메인 클래스 컨버터 기능
컨트롤러에서 식별자로 도메인 클래스를 찾는다.
QueryDSL
- SQL, JPQL을 코드로 작성할 수 있도록 도와주는 빌더 API
- JPA 크리테리아에 비해서 편리하고 실용적임
- 오픈소스
SQL, JPQL의 문제점
- SQL, JPQL은 문자, Type-check 불가능
- 해당 로직 실행 전까지 작동여부 확인 불가
장점
- 문자가 아닌 코드로 작성
- 컴파일 시점에 문법 오류 발견
- 코드 자동완성(IDE 도움)
- 단순하고 쉬움 : 코드 모양이 JPQL과 거의 비슷
- 동적 쿼리
쿼리타입 생성
사용
// JPQL
SELECT m FROM Member m WHERE m.age>18;
// QueryDSL
JPAFactoryQuery query=new JPAQueryFactory(entityManager);
QMember qMember=QMember.member;
List<Member> mebers=query.selectFROM(qMember)
.where(qMember.age.at(18)
.orderBy(qMember.name.desc())
.fetch();
조인
JPAFactoryQuery query=new JPAQueryFactory(entityManager);
QMember qMember=QMember.member;
QTeam qTeam=QTeam.team;
List<Member> mebers=query.selectFROM(qMember)
.join(qMember.team,qTeam)
.where(qTeam.name.eq("teamA")
.fetch();
페이징 API
JPAFactoryQuery query=new JPAQueryFactory(entityManager);
QMember qMember=QMember.member;
List<Member> mebers=query.selectFROM(qMember)
.orderBy(qMember.age.desc())
.offset(10)
.limit(20)
.fetch();
동적 쿼리
String name="Member A";
int age=9;
QMember m=QMember.member;
BooleanBuilder builder=new BooleanBuilder();
if(name!=null){
Builder.and(m.name.contains(name);
if(age!=0){
builder.and(m.age.gt(age));
}
List<Member> members=query.selectFrom(m)
.where(builder)
.fetch();