Skip to main content

Querydslサポートの追加

このTipは@omrzljakにより提出され、@arnaud-deprezにより更新されました

Spring Data のクエリでできることではクエリを作成するのに十分ではない場合があります。@Queryアノテーションや独自に書くこともできますが、私たちの中には、Querydslが提供するようなタイプセーフなクエリを書くのが好きな人もいます。

生成されたPredicateクラス

Querydslの重要な部分は、Predicateと呼ばれるクエリ用に生成されたドメインクラスです。spring-data-mongodbの場合、これらはJavaアノテーション後処理ツールによって生成されます。

Gradleプラグイン

spring-data-mongodbの設定をサポートするQuerydsl用のGradleプラグインもあります。

Mavenプラグイン

Maven用のプラグインもあります。Mavenの構成については、ドキュメントのMavenによるインテグレーションの章で詳しく説明されています。また、次の手順を実行する必要があります。

: org.slf4jはSpring Bootに含まれているので、依存関係に含めないでください。

変更

build.gradle

build.gradleで、依存関係をQuerydsl pluginに追加します。

buildscript {
repositories {
jcenter()
}
dependencies {
classpath "gradle.plugin.com.ewerk.gradle.plugins:querydsl-plugin:1.0.9"
}
}

apply from: 'gradle/querydsl.gradle'

gradle.propertiesで使用するQuerydsl versionを定義してください。

querydsl_version=4.1.4

Then create a the file gradle/querydsl.gradle with

apply plugin: "com.ewerk.gradle.plugins.querydsl"

sourceSets {
main {
java {
srcDir "$buildDir/generated/source/apt/main"
}
}
}

querydsl {
// we use mongodb
springDataMongo = true
querydslSourcesDir = "$buildDir/generated/source/apt/main"
}

dependencies {
compile "com.querydsl:querydsl-mongodb:${querydsl_version}"
compileOnly "com.querydsl:querydsl-apt:${querydsl_version}"
}

MongoDBを使用していますが、Querydslプラグインはその他のオプションもサポートしています。

gradle buildを実行すると、次のような出力が表示されます。 Note: Generating net.jogat.names.domain.QName for [net.jogat.names.domain.Name]

@Documentでアノテートされたドメインクラスごとに、Querydslプラグインは1つのPredicateクラスを生成します。

リポジトリクラスの変更

例えばNameのようなドメインクラスがある場合は、NameRepositoryクラスもあります。すべてのリポジトリクラスをQueryDslPredicateExecutorから拡張するように変更する必要があります。

public interface NameRepository extends MongoRepository<Name, String>, QueryDslPredicateExecutor<Name> {}

これにより、Querydslをサポートする追加のメソッドでリポジトリクラスが拡張されます。 (参考 )

Webサポート

パラメータ化されたリクエストをサポートするために残りのコントローラを拡張するには、org.springframework.data.querydsl.binding.QuerydslPredicateでアノテーションが付けられたcom.mysema.query.types.Predicateをメソッドパラメータに追加する必要があります。

@RestController
@RequestMapping("/api")
class NameResource {

private final NameRepository nameRepository;

public NameResource(NameRepository nameRepository) {
this.nameRepository = nameRepository;
}

また、`NameResourceIntTest`では`QuerydslPredicateArgumentResolver`をサポートする必要があります。

```java
public class NameResourceIntTest {
...
@Autowired
private NameRepository nameRepository;
@Autowired
private QuerydslPredicateArgumentResolver querydslPredicateArgumentResolver;

@PostConstruct
public void setup() {
MockitoAnnotations.initMocks(this);
NameResource nameResource = new nameResource(nameRepository);
this.restNameMockMvc = MockMvcBuilders.standaloneSetup(nameResource)
.setCustomArgumentResolvers(pageableArgumentResolver, querydslPredicateArgumentResolver)
.setMessageConverters(jacksonMessageConverter).build();
}
...
}

詳細については、ドキュメントを参照してください。

タイプセーフなクエリを作成する

GradleまたはMavenプラグインは、Name.classのクエリを記述するために使用できるクラスQNameを生成します。次にJavaの例を示します。

QName name = QName.name;

// リスト"categorie"に文字列"TOP_EVER"が含まれるすべての名前をカウントします
nameRepository.count(name.categories.contains("TOP_EVER"));