본문 바로가기
IT/JPA

Spring Data JPA + QueryDsl

by 최고영회 2019. 9. 9.
728x90
반응형
SMALL

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/

 

Querydsl - 레퍼런스 문서

 

www.querydsl.com

 

728x90
반응형
LIST