Spring

[Spring] Querydsl 적용하기

quedevel 2020. 3. 16. 09:26
728x90
반응형

JPA를 이용하여 검색을 하기 위해 동적 쿼리를 작성할 필요가 있었다.

검색을 통해 알아본바로 Querydsl를 사용하면 가능하다고 한다.

내용은 공식 래퍼런스에 잘 나와있기에 패쓰

http://www.querydsl.com/static/querydsl/4.0.1/reference/ko-KR/html_single/#intro

 

Querydsl - 레퍼런스 문서

본 절에서는 SQL 모듈의 쿼라 타입 생성과 쿼리 기능을 설명한다. com.querydsl.sql.Configuration 클래스를 이용해서 설정하며, Configuration 클래스는 생성자 인자로 Querydsl SQL Dialect를 취한다. 예를 들어, H2 DB 사용시 다음과 같이 생성한다. SQLTemplates templates = new H2Templates(); Configuration configuration = new Configura

www.querydsl.com

 

일단 maven에 2가지 추가

		<!-- https://mvnrepository.com/artifact/com.querydsl/querydsl-apt -->
		<dependency>
			<groupId>com.querydsl</groupId>
			<artifactId>querydsl-apt</artifactId>
			<version>4.3.0</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/com.querydsl/querydsl-jpa -->
		<dependency>
			<groupId>com.querydsl</groupId>
			<artifactId>querydsl-jpa</artifactId>
			<version>4.3.0</version>
		</dependency>

plugin 내용 추가

<!-- Querydsl 을 사용하려면 엔티티를 기반으로 쿼리 타입이라는 쿼리용 클래스를 생성해야 한다. -->
<!-- 쿼리 타입을 생성해주는 플러그인을 설정해줘야 함 -->
<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>

플러그인까지 추가하고 보니 target/generated-sources/java 및에 Q클래스들이 생성이 되었다.

QuerydslConfig.java

@Configuration
public class QuerydslConfig {

    // EntityManager 란?
    // 엔터티 매니저는 엔터티를 저장하는 메모리상의 데이터베이스라고 생각하면 될 것같다. 
    // 엔터티 매니저는 엔터티를 저장하고 수정하고 삭제하고 조회하는 등 엔터티와 관련된 모든일을 한다.
    // 엔티티 매니저는 여러 스레드가 동시에 접근하면 동시성 문제가 발생하므로 스레드 간에 절대 공유하면 안된다.
    
    // @PersistenceContext 란?
    // 영속성 컨텍스트란 엔티티(Entity)를 영구 저장 하는 환경을 말한다. 
    // 엔티티 매니저로 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리한다.
    // 영속성 컨텍스트는 엔티티 매니저(Session)를 생성할 때 하나 만들어진다. 
    // 그리고 엔티티 매니저(Session)를 통해서 영속성 컨텍스트에 접근할 수 있고 영속성 컨텍스트를 관리 할 수 있다.
    
    @PersistenceContext
    private EntityManager entityManager;


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

 

BoardRepositorySupport.java

@Repository
public class BoardRepositorySupport extends QuerydslRepositorySupport {

    private final JPAQueryFactory queryFactory;

    public BoardRepositorySupport(JPAQueryFactory queryFactory) {
        super(Board.class);
        this.queryFactory = queryFactory;
    }

    public List<Board> findByTitle(String title){
        return queryFactory.selectFrom(board).where(board.title.eq(title)).fetch();
    }

}

 

작성후 간단한 테스트 진행

BoardRepositorySupportTests.java

@Slf4j
@SpringBootTest
public class BoardRepositorySupportTests {

    @Autowired
    private BoardRepository boardRepository;

    @Autowired
    private BoardRepositorySupport boardRepositorySupport;

    @Test
    public void querydslTest(){
        String keyword = "JAVA";
        int result1 = boardRepository.findByTitleContaining(keyword).size();
        log.info("result1 : "+result1);

        int result2 = boardRepositorySupport.findByTitle(keyword).size();
        log.info("result2 : "+result2);
    }
    
}

 

결과

 java.lang.NoSuchMethodError: com.querydsl.jpa.JPQLSerializer.getConstantToAllLabels()Ljava/util/Map;
	at com.querydsl.jpa.JPQLSerializer.visitConstant(JPQLSerializer.java:325)
	at com.querydsl.core.support.SerializerBase.visit(SerializerBase.java:190)
	at com.querydsl.core.support.SerializerBase.visit(SerializerBase.java:31)
	at com.querydsl.core.types.ConstantImpl.accept(ConstantImpl.java:140)
	at com.querydsl.core.support.SerializerBase.handle(SerializerBase.java:92)
	at com.querydsl.core.support.SerializerBase.visitOperation(SerializerBase.java:270)
	at com.querydsl.jpa.JPQLSerializer.visitOperation(JPQLSerializer.java:437)
	at com.querydsl.core.support.SerializerBase.visit(SerializerBase.java:231)
	at com.querydsl.core.support.SerializerBase.visit(SerializerBase.java:31)
	at com.querydsl.core.types.OperationImpl.accept(OperationImpl.java:83)
	at com.querydsl.core.support.SerializerBase.handle(SerializerBase.java:92)
	at com.querydsl.jpa.JPQLSerializer.serialize(JPQLSerializer.java:220)
	at com.querydsl.jpa.JPAQueryBase.serialize(JPAQueryBase.java:60)
	at com.querydsl.jpa.JPAQueryBase.serialize(JPAQueryBase.java:50)
	at com.querydsl.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:98)
	at com.querydsl.jpa.impl.AbstractJPAQuery.createQuery(AbstractJPAQuery.java:94)
	at com.querydsl.jpa.impl.AbstractJPAQuery.fetch(AbstractJPAQuery.java:201)
	at com.example.sun0311.supports.BoardRepositorySupport.findByTitle(BoardRepositorySupport.java:30)
	at com.example.sun0311.supports.BoardRepositorySupport$$FastClassBySpringCGLIB$$a69ddc79.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769)

 

응 역시 에러 폭발^^

정말 한번에 잘되는법은 없구나....

728x90
반응형