Gradle を使った Querydsl MongoDB のコード生成

前回の Querydsl JPA に続き、今回は Querydsl MongoDB のコード生成を Gradle で実施してみました。

ソースは http://github.com/fits/try_samples/tree/master/blog/20150330/

Gradle を使ったコード生成

Querydsl MongoDB の場合は、前回 のビルド定義ファイルから依存モジュールとアノテーションプロセッサクラスを以下のように変えるだけです。 (querydsl-apt はそのまま使います)

  • querydsl-jpaquerydsl-mongodb へ変更
  • javaee-apimorphia へ変更
  • com.mysema.query.apt.jpa.JPAAnnotationProcessor を com.mysema.query.apt.morphia.MorphiaAnnotationProcessor へ変更

なお、エンティティクラスは Morphia のアノテーションを使って定義します。

(a) compileJava タスクでコード生成とコンパイルを実施

compileJava タスクの実行時に Querydsl のコード生成とコンパイルの両方を実施するタイプです。

build1.gradle
apply plugin: 'java'

repositories {
    jcenter()
}

configurations {
    apt
}

dependencies {
    apt 'com.mysema.querydsl:querydsl-apt:3.6.2'

    // Querydsl MongoDB 用の依存モジュール
    compile 'com.mysema.querydsl:querydsl-mongodb:3.6.2'
    compile 'org.mongodb.morphia:morphia:0.110'
}

compileJava {
    classpath += configurations.apt

    options.compilerArgs += [
        '-processor', 'com.mysema.query.apt.morphia.MorphiaAnnotationProcessor'
    ]
}

jar {
    excludes << '**/*.java'
}

ビルド結果は以下の通りです。

ビルド例
> gradle -b build1.gradle build

:compileJava
注意:Running MorphiaAnnotationProcessor
注意:Serializing Entity types
注意:Generating sample.model.QProduct for [sample.model.Product]
注意:Serializing Embeddable types
注意:Generating sample.model.QVariation for [sample.model.Variation]
注意:Running MorphiaAnnotationProcessor
注意:Running MorphiaAnnotationProcessor
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

自動生成されるソースの場所やクラス名の先頭に Q が付くのは前回と同じです。

(b) 別タスクでコード生成

Querydsl のコード生成を別タスク (下記の generate) で実施するタイプです。

Querydsl は IDE で利用すると思いますので、こちらの方が使い易いと思います。

build2.gradle
apply plugin: 'java'

def qdslDestDir = 'src/main/qdsl-generated'

repositories {
    jcenter()
}

configurations {
    apt
}

dependencies {
    apt 'com.mysema.querydsl:querydsl-apt:3.6.2'

    compile 'com.mysema.querydsl:querydsl-mongodb:3.6.2'
    compile 'org.mongodb.morphia:morphia:0.110'
}

task generate(type: JavaCompile) {

    source = sourceSets.main.java
    classpath = configurations.compile + configurations.apt

    destinationDir = new File(qdslDestDir)

    options.compilerArgs += [
        '-proc:only', 
        '-processor', 'com.mysema.query.apt.morphia.MorphiaAnnotationProcessor'
    ]
}

compileJava {
    dependsOn generate
    sourceSets.main.java.srcDir qdslDestDir
}

clean {
    delete qdslDestDir
}

ビルド結果は以下の通りです。

ビルド例
> gradle -b build2.gradle build

:generate
注意:Running MorphiaAnnotationProcessor
注意:Serializing Entity types
注意:Generating sample.model.QProduct for [sample.model.Product]
注意:Serializing Embeddable types
注意:Generating sample.model.QVariation for [sample.model.Variation]
注意:Running MorphiaAnnotationProcessor
注意:Running MorphiaAnnotationProcessor
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build

BUILD SUCCESSFUL

サンプルアプリケーション

最後に、簡単なサンプルアプリケーションを実装し実行してみます。

ビルド定義

別タスクによるコード生成タイプ (b) のビルド定義をベースに以下のようなビルド定義を用意しました。

build.gradle
apply plugin: 'application'

def enc = 'UTF-8'
tasks.withType(AbstractCompile)*.options*.encoding = enc

def qdslDestDir = 'src/main/qdsl-generated'

repositories {
    jcenter()
}

configurations {
    apt
}

dependencies {
    apt 'com.mysema.querydsl:querydsl-apt:3.6.2'

    compile 'com.mysema.querydsl:querydsl-mongodb:3.6.2'
    compile 'org.mongodb.morphia:morphia:0.110'
}

task generate(type: JavaCompile) {

    source = sourceSets.main.java
    classpath = configurations.compile + configurations.apt

    destinationDir = new File(qdslDestDir)

    options.compilerArgs += [
        '-proc:only',
        '-processor', 'com.mysema.query.apt.morphia.MorphiaAnnotationProcessor'
    ]
}

compileJava {
    dependsOn generate
    sourceSets.main.java.srcDir qdslDestDir
}

clean {
    delete qdslDestDir
}

mainClassName = 'sample.App'

エンティティクラス

Morphia 用のエンティティクラスとして以下を定義しました。

src/main/sample/model/Product.java
package sample.model;

import org.mongodb.morphia.annotations.*;
import org.bson.types.ObjectId;

import java.util.ArrayList;
import java.util.List;

@Entity
public class Product {
    @Id
    private ObjectId id;
    private String name;
    @Embedded
    private List<Variation> variationList = new ArrayList<>();

    public Product() {
    }

    public Product(String name) {
        setName(name);
    }

    public void setId(ObjectId id) {
        this.id = id;
    }

    public ObjectId getId() {
        return id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public List<Variation> getVariationList() {
        return variationList;
    }
}
src/main/sample/model/Variation.java
package sample.model;

import org.mongodb.morphia.annotations.Embedded;

@Embedded
public class Variation {
    private String size;
    private String color;

    public Variation() {
    }

    public Variation(String size, String color) {
        setSize(size);
        setColor(color);
    }

    public String getSize() {
        return size;
    }
    public void  setSize(String size) {
        this.size = size;
    }

    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
}

アプリケーションクラス

Product を保存した後に、Querydsl MongoDB の機能で簡単な検索を行う処理を実装しました。

src/main/sample/App.java
package sample;

import com.mongodb.MongoClient;
import com.mysema.query.mongodb.morphia.MorphiaQuery;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.Morphia;
import sample.model.Product;
import sample.model.QProduct;
import sample.model.Variation;

import java.net.UnknownHostException;

public class App {
    public static void main(String... args) throws UnknownHostException {
        Morphia morphia = new Morphia();
        Datastore ds = morphia.createDatastore(new MongoClient(), "sample");

        Product p = new Product("test" + System.currentTimeMillis());

        p.getVariationList().add(new Variation("L", "black"));
        p.getVariationList().add(new Variation("M", "white"));

        ds.save(p);

        // Querydsl MongoDB を使った検索処理
        QProduct qp = QProduct.product;
        MorphiaQuery<Product> query = new MorphiaQuery<>(morphia, ds, qp);

        query.where(qp.name.like("test%")).list().forEach(App::printProduct);
    }

    private static void printProduct(Product p) {
        System.out.println("----------");

        System.out.println(p.getId() + ", " + p.getName());

        p.getVariationList().forEach(v ->
                System.out.println(v.getColor() + ", " + v.getSize()));

    }
}

実行

まず、MongoDB を起動しておきます。 今回は開発版の MongoDB 3.1.0 (SSL版) を使用しました。

MongoDB 起動
> mongod --dbpath data

・・・
2015-03-29T23:50:32.137+0900 I CONTROL  [initandlisten] ** NOTE: This is a development version (3.1.0) of MongoDB.
・・・
2015-03-29T23:50:32.685+0900 I NETWORK  [initandlisten] waiting for connections on port 27017

実行結果は以下の通りです。

実行結果
> gradle run

・・・
:run
3 29, 2015 11:52:47 午後 org.mongodb.morphia.logging.MorphiaLoggerFactory choose LoggerFactory
情報: LoggerImplFactory set to org.mongodb.morphia.logging.jdk.JDKLoggerFactory
----------
551811bfcc87cb6a0dcb43fd, test1427640767733
black, L
white, M

BUILD SUCCESSFUL

MongoDB shell を使って登録内容を確認してみます。

データ確認
> mongo
・・・
MongoDB shell version: 3.1.0
connecting to: test
Welcome to the MongoDB shell.
・・・

> use sample
switched to db sample

> db.Product.find()
{ "_id" : ObjectId("551811bfcc87cb6a0dcb43fd"), "className" : "sample.model.Product", "name" : "test1427640767733", "variationList" : [ { "size" : "L", "color"
: "black" }, { "size" : "M", "color" : "white" } ] }