[querydsl] Data JPA와 Querydsl 설정과 사용
버전과 환경은 아래와 같다.
- Spring Boot:1.4
- Spring Data JPA + Querydsl
- Gradle
- Intellij idea
1 2 3 4 5 6 7 8 9 10 11 | dependencies { def querydslVersion = "4.1.4" /** * querydsl dependency */ compile ("com.querydsl:querydsl-core:$querydslVersion") compile ("com.querydsl:querydsl-apt:$querydslVersion") compile ("com.querydsl:querydsl-jpa:$querydslVersion") } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | def queryDslOutput = file("src-gen/main/java") sourceSets { main { java { srcDir "src-gen/main/java" } } } task generateQueryDSL(type: JavaCompile, group: 'build') { doFirst { if (!queryDslOutput.exists()) { logger.info("Creating `$queryDslOutput` directory") if (!queryDslOutput.mkdirs()) { throw new InvalidUserDataException("Unable to create `$queryDslOutput` directory") } } } source = sourceSets.main.java classpath = configurations.compile options.compilerArgs = [ "-proc:only", "-processor", "com.querydsl.apt.jpa.JPAAnnotationProcessor" ] destinationDir = queryDslOutput } compileTestJava.dependsOn(generateQueryDSL) | cs |
1 2 3 | springBoot { mainClass = "net.woniper.querydsl.SpringBootQuerydslApplication" } | cs |
1 2 3 4 5 6 | /** * gradle clean task 실행 시 querydsl 경로 제거 */ clean { delete queryDslOutput } | cs |
querydsl에서는 QClass라는 파일이 생성되어야 한다. gradle clean task 실행 시 QClass를 모두 삭제한다. 전체 소스는 github에 있다. 참고하자. (제일 하단에 링크 참고)
JPA Entity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | package net.woniper.querydsl.domain; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity public class Foo { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "foo_id") private Long id; @Column(name = "bar") private String bar; public Foo() {} public Foo(String bar) { setBar(bar); } public Long getId() { return id; } public Foo setId(Long id) { this.id = id; return this; } public String getBar() { return bar; } public Foo setBar(String bar) { this.bar = bar; return this; } @Override public String toString() { return "Foo{" + "id=" + id + ", bar='" + bar + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Foo)) return false; Foo foo = (Foo) o; if (getId() != null ? !getId().equals(foo.getId()) : foo.getId() != null) return false; return getBar() != null ? getBar().equals(foo.getBar()) : foo.getBar() == null; } @Override public int hashCode() { int result = getId() != null ? getId().hashCode() : 0; result = 31 * result + (getBar() != null ? getBar().hashCode() : 0); return result; } } | cs |
JPA나 Entity Class를 따로 설명하지 않겠다. querydsl에서 생성되는 QClass는 바로 이 JPA Entity를 기준으로 QClass를 생성한다. 앞서 gradle 설정이 바로 이 Entity를 기준으로 QClass를 생성하기 위한 설정이다.
Repository
1 2 3 4 5 6 7 8 9 10 11 | package net.woniper.querydsl.repository; import net.woniper.querydsl.domain.Foo; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.querydsl.QueryDslPredicateExecutor; public interface FooRepository extends JpaRepository<Foo, Long>, QueryDslPredicateExecutor<Foo> { Foo findByBar(String bar); } | cs |
8라인을 보면 JpaRepository와 QueryDslPredicateExecutor를 상속받았다. JPA에서 Repository 선언은 JpaRepository 상속으로 충분하지만, querydsl을 사용하려면 QueryDslPredicateExecutor 또한 상속이 필요하다.
QClass 생성
기본 설정은 끝났다. QClass가 정상적으로 생성되는지 확인해보자. 앞서 설명했던 gradle bootRepackage 명령어를 실행시켜 보자. 생성 위치인 "src/main/generated" 경로에 QFoo Class가 생성된다면 정상적으로 설정된것이다. (gradle clean 명령어도 실행시켜보자. "src/main/generated" 경로가 삭제되어야한다.
Test
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | package net.woniper.querydsl; import com.querydsl.core.BooleanBuilder; import net.woniper.querydsl.domain.Foo; import net.woniper.querydsl.domain.QFoo; import net.woniper.querydsl.repository.FooRepository; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @RunWith(SpringRunner.class) @SpringBootTest public class SpringBootQuerydslApplicationTests { @Autowired private FooRepository repository; @Before public void setUp() throws Exception { repository.save(new Foo("foo1")); repository.save(new Foo("foo2")); repository.save(new Foo("foo3")); repository.save(new Foo("bar1")); repository.save(new Foo("bar2")); repository.save(new Foo("bar3")); } @Test public void testFoo() { Foo foo1 = repository.findByBar("foo1"); assertThat(foo1.getBar(), is("foo1")); } @Test public void testQuerydslFindLikeBar() throws Exception { // given String likeWhere = "bar%"; QFoo foo = QFoo.foo; BooleanBuilder builder = new BooleanBuilder().and(foo.bar.like(likeWhere)); // when Iterable<Foo> foos = repository.findAll(builder); // then foos.forEach(System.out::println); foos.forEach(f -> assertTrue(f.getBar().startsWith("bar"))); } } | cs |
테스트를 돌려보자.
마무리
프로젝트 설정과 코드를 세세한 설명이 부족하다는것은 알지만, 이 포스팅은 Data-JPA + querydsl + intellij 상황에서 어떻게 설정해야되는지 삽질 결과를 공유하기 위함이다. 상세 설정과 코드는 https://github.com/woniper/spring-example/tree/master/spring-boot-querydsl 여기를 참고하자.
출처 : https://blog.woniper.net/317?category=531455