해당 글은 QueryDSL 에 대한 소개, 장점 등은 없습니다. 오직 기존 학습을 위한 코드를 개선하는 것을 기록하는 데 있습니다.
// 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 시도
@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 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 {
}