[QueryDSL] 기존 학습 코드 개선하기

DevHwan·2022년 12월 3일
0

해당 글은 QueryDSL 에 대한 소개, 장점 등은 없습니다. 오직 기존 학습을 위한 코드를 개선하는 것을 기록하는 데 있습니다.

Gradle 설정 및 QClass 생성

// queryDSL 설정
implementation "com.querydsl:querydsl-jpa"
implementation "com.querydsl:querydsl-core"
implementation "com.querydsl:querydsl-collections"
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa" // querydsl JPAAnnotationProcessor 사용 지정
annotationProcessor "jakarta.annotation:jakarta.annotation-api" // java.lang.NoClassDefFoundError (javax.annotation.Generated) 대응 코드
annotationProcessor "jakarta.persistence:jakarta.persistence-api" // java.lang.NoClassDefFoundError (javax.annotation.Entity) 대응 코드

compileJava 이후에 Build 또는 버전에 따라 compileQueryDSL 시도

Java Config

@Configuration
public class QuerydslConfiguration {

    @PersistenceContext
    private EntityManager entityManager;

    @Bean
    public JPAQueryFactory jpaQueryFactory() {
        return new JPAQueryFactory(entityManager);
    }
}

QueryDSL에 사용될 클래스인 Q클래스는 별도의 패키지에 자동 생성되게 된다. 이것들을 프로젝트 어디서든 해당 Bean을 주입받아서 사용할 수 있도록 Config 설정을 해준다.

기본적인 사용

바로 사용에 앞서서 기존에 사용했던 Entity 중 하나를 선택한다.

@Entity
@Getter
@Setter
public class Member {

    @Id
    @GeneratedValue
    @Column(name = "member_id")
    private Long id;

    private String name;

    @Embedded
    private Address address;

    @OneToMany(mappedBy = "member")
    private List<Order> orders = new ArrayList<>();
}
public interface MemberRepository extends JpaRepository<Member, Long> {
}

테스트로 데이터를 넣고 검증할 Repository도 하나 생성한다.

이후에 QueryDSL을 사용할 Repository를 별도로 생성한다. QuerydslRepositorySupport 클래스를 extends 하고 JPAQueryFactory를 생성자 주입받는다. 이전에 Build를 통해서 QClass를 생성한 것들을 해당 클래스 에서 사용한다.

~~~ 생략 ~~~
// 이게 중요
import static jpabook.jpashop.domain.QMember.member;

@Repository
public class MemberRepositorySupport extends QuerydslRepositorySupport {

    private final JPAQueryFactory queryFactory;

    public MemberRepositorySupport(JPAQueryFactory queryFactory) {
        super(Member.class);
        this.queryFactory = queryFactory;
    }

    public List<Member> findByName(String name) {
        return queryFactory
                .selectFrom(member)
                .where(member.name.eq(name))
                .fetch();
    }
}

Spring Data JPA + QueryDSL

구현에 따라 Spring Data JPA Custom Repository를 사용할 수 있고, 원한다면 QueryDSL Repository만 운용할 수 도 있다. 보통 선호하는 방식을 이용하고, 정답은 없으나 여러 개의 Repository를 의존성으로 받아야 하는 경우 CustomRepository를 인터페이스로 선언하고 이를 implements 하는 Repository를 별도로 만들고, 최종적으로 JpaRepository와 구현체를 상속받는 Repository를 만들면 된다.

public interface MemberRepositoryCustom {
    public List<Member> findAllOrderByDesc();

    public List<Member> findByName(String name);
}
@RequiredArgsConstructor
public class MemberRepositoryImpl implements MemberRepositoryCustom {
    private final JPAQueryFactory queryFactory;

    @Override
    public List<Member> findAllOrderByDesc() {
        return queryFactory
                .selectFrom(member)
                .orderBy()
                .fetch();
    }

    @Override
    public List<Member> findByName(String name) {
        return queryFactory
                .selectFrom(member)
                .where(member.name.eq(name))
                .fetch();
    }
}
public interface MemberRepositoryIn extends JpaRepository<Member, Long>, MemberRepositoryCustom {
}
profile
달리기 시작한 치타

0개의 댓글