2019/09/06 - [IT/JPA] - JPQL, NativeSQL, Criteria, QueryDSL, JOOQ... 에서 살펴 본 것 처럼
Spring Data JPA 만으로는 복잡한 구조의 어플리케이션을 구성하는데 한계가 있다.
QueryDsl 을 사용하는 방법을 간단하게 정리 해 본다.
먼저 pom.xml 에 아래 dependency를 추가 한다.
<!-- querydsl -->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
</dependency>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
QueryDsl 은 Entity Class 를 wrapping 한 Qxxx class 를 사용하기 때문에
위와 같이 apt 를 이용해서 Entity Annotation이 있는 클래스들을 Qxxx class 로 자동 생성하도록 설정한다.
위와 같이 설정하면 설정된 경로에 아래와 같이 Q+entity.java 들이 자동 생성된다.
QueryDsl 은 이 클래스들을 이용한다.
기존의 Rpository는 아래와 같았다.
@Repository
public interface JsfuncRepository extends JpaRepository<Jsfunc, Long> {
List<Jsfunc> findByName(String name);
}
JsfuncRepositoryCustom Interface를 하나 만들자.
public interface JsfuncRepositoryCustom {
List<Jsfunc> findRecentlyRegistered(int limit);
}
이 인터페이스에는 QueryDsl 로 복잡한 SQL을 수행하기 위한 method들을 선언해 둔다.
그리고 위 interface를 구현하는 implements class 를 만들자.
@Transactional(readOnly = true)
public class JsfuncRepositoryImpl extends QuerydslRepositorySupport implements JsfuncRepositoryCustom {
public JsfuncRepositoryImpl() {
super(Jsfunc.class);
}
@Override
public List<Jsfunc> findRecentlyRegistered(int limit) {
final QJsfunc jsfunc = QJsfunc.jsfunc;
return from(jsfunc)
.orderBy(jsfunc.no.desc())
.limit(limit)
.fetch();
}
이제 기존의 Repository에 JsfuncRepositoryCustom 을 extends에 추가 하자.
@Repository
public interface JsfuncRepository extends JpaRepository<Jsfunc, Long>, JsfuncRepositoryCustom {
List<Jsfunc> findByName(String name);
}
이제 간단한 CUD는 JsfuncRepository에서 복잡한 R은 JsfuncRepositoryImpl 에서 처리하면 된다.
Service 입장에서는 둘의 구분을 알 필요 없다. 그냥 JsfuncRepository 만 @Autowired 해서 사용하면 된다.
@Service
public class JsfuncService {
@Autowired
private JsfuncRepository jsRepo;
@Transactional
public void delete(long no){
Jsfunc js = jsRepo.findById(no).orElseThrow(() -> new ResourceNotFoundException("Jsfunc", "no", no));
jsRepo.delete(js);
}
public List<Jsfunc> findLimit(int limit){
return jsRepo.findRecentlyRegistered(limit);
}
}
QueryDsl 의 레퍼런스 문서 : http://www.querydsl.com/static/querydsl/3.7.2/reference/ko-KR/html/
'IT > JPA' 카테고리의 다른 글
LocalDate, LocalTime JPA Timezone 문제 (0) | 2020.03.25 |
---|---|
[JPA] null value was assigned to a property of primitive type setter of (0) | 2019.11.14 |
JPQL, NativeSQL, Criteria, QueryDSL, JOOQ... (0) | 2019.09.06 |
@OneToMany 단방향을 @ManyToOne 양방향으로 (2) | 2019.08.28 |
Spring Data JPA 기초 #1 (7) | 2019.01.07 |