LoginSignup
1
3

Eclipse + Java + Gradle の環境で Doma を動かす

Last updated at Posted at 2024-05-19

はじめに

この記事では、データベースアクセスフレームワークである Doma を利用する際の開発環境構築についてノウハウを紹介します。
簡単なサンプルアプリケーションを作りながら解説します。

前提

バージョンなど

開発マシンは macOS を想定しますが、Windows と異なるところはないと思います。

IDE、ツール、ライブラリ等のバージョンは以下のとおりです。

  • Eclipse IDE for Java Developers 2024-03 (4.31.0)
  • Java 17.0.10(Eclipse のデフォルト)
  • Gradle 8.1.1(Eclipse で Gradle Project 作成時に利用されるバージョン)
  • Doma 2.58.0

Eclipse の仕組みを踏まえた戦略

Eclipse は以下のようなさまざまな設定ファイルを参照して動きます。

  • .classpath : どのライブラリのどのバージョンを使うのかといったクラスパス情報
  • .factorypath : アノテーションプロセッサーのライブラリのパス情報
  • .project : プロジェクト名などのメタ情報
  • .settings : Eclipseの画面からの設定項目など複数ファイルを管理するフォルダ

これらのファイルは Eclipse の 画面上で設定を行うことで出力できますが、その場合の問題点はビルドファイルと Eclipse の設定ファイルで二重管理が必要となってしまうことです。 二重管理を避けるために、ビルドファイルを一次情報としてビルドファイルから Eclipse の設定ファイルを自動生成するのが基本的な戦略となります。

Eclipse から Gradle Project の作成

Eclipse 上部のメニューから File > New > Project... > Gradle > Gradle Project を選択しダイアログを進めます。プロジェクト名には example を入力して Finish ボタンを押します。

そうすると、example と lib の2つのプロジェクトが作成されます。

生成された build.gradle の確認

lib プロジェクトの build.gradle を確認しましょう。

build.gradle
/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java library project to get you started.
 * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
 * User Manual available at https://docs.gradle.org/8.1.1/userguide/building_java_projects.html
 */

plugins {
    // Apply the java-library plugin for API and implementation separation.
    id 'java-library'
}

repositories {
    // Use Maven Central for resolving dependencies.
    mavenCentral()
}

dependencies {
    // Use JUnit Jupiter for testing.
    testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1'

    // This dependency is exported to consumers, that is to say found on their compile classpath.
    api 'org.apache.commons:commons-math3:3.6.1'

    // This dependency is used internally, and not exposed to consumers on their own compile classpath.
    implementation 'com.google.guava:guava:31.1-jre'
}

// Apply a specific Java toolchain to ease working on different environments.
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

tasks.named('test') {
    // Use JUnit Platform for unit tests.
    useJUnitPlatform()
}

上部のコメントにあるように、これはサンプル用のビルドファイルです。

まずはこの状態で動作確認したいところですが、私の環境では Eclipse 上から JUnit が動きませんでした。Eclipse の JUnit と build.gradle に記載の JUnit のバージョンに互換性がないからだと思われます。

build.gradle の修正

オリジナルの build.gradle を以下の内容で置換します。

build.gradle
plugins {
    id 'java-library'
    // Eclipse のアノテーションプロセッシング関連の設定ファイルを生成するプラグイン
    id 'com.diffplug.eclipse.apt' version '3.44.0'
    // Doma を使ったビルドをサポートするプラグイン
    id 'org.domaframework.doma.compile' version '2.0.0'
}

repositories {
    mavenCentral()
}

dependencies {
    // 最新の JUnit を利用。
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.2'

    // Doma の核となるライブラリ。ビルド時も実行時も必要。
    implementation 'org.seasar.doma:doma-core:2.58.0'

    // Doma のログをSLF4J経由で出力するライブラリ。
    implementation("org.seasar.doma:doma-slf4j:2.58.0")

    // SLF4J の実装ライブラリ。
    runtimeOnly("ch.qos.logback:logback-classic:1.2.11")

    // Doma のアノテーションプロセッサー。ビルド時のみ必要。
    annotationProcessor 'org.seasar.doma:doma-processor:2.58.0'

    // 本サンプルで利用する H2 Database Engine。データベースでありJDBCドライバである。
    runtimeOnly 'com.h2database:h2:2.2.224'
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

tasks.named('test') {
    useJUnitPlatform()
}

// Eclipse 関連の設定
eclipse {
    // .classpath ファイルに関する設定
    classpath {
        file {
            whenMerged { classpath ->
                // アノテーションプロセッサーで生成したソースコードを保存するフォルダ
                def folder = new org.gradle.plugins.ide.eclipse.model.SourceFolder(".apt_generated", "bin/main")
                // クラスパスに追加
                classpath.entries.add(folder)
                // 存在しなければ作成
                def dir = file(folder.path)
                if (!dir.exists()) {
                    dir.mkdir()
                }
            }
        }
    }
    // .project ファイルに関する設定
    project {
        buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
        natures 'org.eclipse.buildship.core.gradleprojectnature'
    }
    // Eclipse から "Refresh Gradle Project" を呼び出した時に実行されるタスク
    synchronizationTasks 'cleanEclipse', 'eclipse'
}

ポイントは以下のとおりです。

  • plugins ブロックに Eclipse や Doma に関するプラグインを指定します。
  • dependencies ブロックに Doma 関連のライブラリを記載します。JUnit のライブラリも変更します。
  • eclipse ブロックに Eclipse 関連の設定ファイルを生成するための記述をします。

特にコメントを入れていないところはオリジナルの build.gradle にも記載があったものです。詳細はオリジナルの方のコメントを参照ください。

動作確認(build.gradle の記述に問題ないか?)

では、置換した build.gradle が正しく動くか確認しましょう。

Refresh Gradle Project の実行

example か lib プロジェクトを右クリックして Gradle > Refresh Gradle Project を実行してください。Refresh Gradle Project を行うと build.gradle に記載した synchronizationTasks に指定したタスクが動きます。synchronizationTasks には 以下の2つの Gradle タスクを設定していました。

  • cleanEclipse: Eclipse の設定ファイルを削除するタスク
  • eclipse: Eclipse 設定ファイルを生成するタスク

Refresh Gradle Project の実行結果は Eclipse のコンソール上に以下のように出力されます。BUILD SUCCESSFUL の文字列が出力されていれば成功です。

> Task :lib:cleanEclipseClasspath
> Task :lib:cleanEclipseFactorypath
> Task :lib:cleanEclipseJdt
> Task :lib:cleanEclipseJdtApt
> Task :lib:cleanEclipseProject
> Task :lib:cleanEclipse UP-TO-DATE
> Task :lib:eclipseClasspath
> Task :lib:eclipseFactorypath
> Task :lib:eclipseJdt
> Task :lib:eclipseJdtApt
> Task :lib:eclipseProject
> Task :lib:eclipse

Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See https://docs.gradle.org/8.1.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 712ms
11 actionable tasks: 10 executed, 1 up-to-date

コンソールへの出力を確認するには、コンソールビューの右上の Display Selected Console アイコンから [Gradle Operations] を選んでください。

JUnit の実行

次に lib プロジェクトを右クリックして Run As > JUnit Test を選択します。
JUnit ビューにグリーンのバーが出力されれば成功です。

Doma を利用するコードの追加

lib プロジェクトの src/main/java フォルダの example パッケージに次のクラスを追加します。

DbConfig.java
package example;

import java.util.Objects;

import javax.sql.DataSource;

import org.seasar.doma.jdbc.Config;
import org.seasar.doma.jdbc.JdbcLogger;
import org.seasar.doma.jdbc.dialect.Dialect;
import org.seasar.doma.jdbc.dialect.H2Dialect;
import org.seasar.doma.jdbc.tx.LocalTransactionDataSource;
import org.seasar.doma.jdbc.tx.LocalTransactionManager;
import org.seasar.doma.jdbc.tx.TransactionManager;
import org.seasar.doma.slf4j.Slf4jJdbcLogger;

public class DbConfig implements Config {

    private final Dialect dialect;
    private final DataSource dataSource;
    private final JdbcLogger jdbcLogger;
    private final TransactionManager transactionManager;

    public DbConfig(Dialect dialect, DataSource dataSource, JdbcLogger jdbcLogger,
            TransactionManager transactionManager) {
        this.dialect = Objects.requireNonNull(dialect);
        this.dataSource = Objects.requireNonNull(dataSource);
        this.jdbcLogger = Objects.requireNonNull(jdbcLogger);
        this.transactionManager = Objects.requireNonNull(transactionManager);
    }

    @Override
    public JdbcLogger getJdbcLogger() {
        return jdbcLogger;
    }

    @Override
    public Dialect getDialect() {
        return dialect;
    }

    @Override
    public DataSource getDataSource() {
        return dataSource;
    }

    @Override
    public TransactionManager getTransactionManager() {
        return transactionManager;
    }

    public static DbConfig of() {
        var dialect = new H2Dialect();
        var dataSource = new LocalTransactionDataSource("jdbc:h2:mem:tutorial;DB_CLOSE_DELAY=-1", "sa", null);
        var jdbcLogger = new Slf4jJdbcLogger();
        var transactionManager = new LocalTransactionManager(dataSource, jdbcLogger);
        return new DbConfig(dialect, dataSource, jdbcLogger, transactionManager);
    }
}
Person.java
package example;

import org.seasar.doma.Entity;
import org.seasar.doma.Id;

@Entity
public class Person {

    @Id
    Integer id;

    String name;
}
PersonDao.java
package example;

import java.util.List;

import org.seasar.doma.Dao;
import org.seasar.doma.Insert;
import org.seasar.doma.Script;
import org.seasar.doma.Select;
import org.seasar.doma.Sql;

@Dao
public interface PersonDao {

    @Script
    @Sql("""
            create table if not exists person(
              id integer not null primary key,
              name varchar(20)
            )
            """)
    void createTable();

    @Select
    List<Person> selectAll();

    @Insert
    int insert(Person person);
}

lib プロジェクトの src/main/resources/META-INF/example/PersonDao フォルダに次の SQL ファイルを追加します。

selectAll.sql
select /*%expand*/* from person

lib プロジェクトの src/test/java フォルダの example パッケージに次のクラスを追加します。

PersonDaoTest
package example;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

public class PersonDaoTest {

    // データベースの設定
    DbConfig dbConfig = DbConfig.of();
    // DAO
    PersonDao dao = new PersonDaoImpl(dbConfig);

    @Test
    public void test() {
        // トランザクション内で実行
        dbConfig.getTransactionManager().required(() -> {
            dao.createTable(); // テーブルの作成

            var person1 = new Person();
            person1.id = 1;
            person1.name = "abc";
            dao.insert(person1); // 追加

            var person2 = new Person();
            person2.id = 2;
            person2.name = "def";
            dao.insert(person2); // 追加

            var people = dao.selectAll(); // 全件取得
            assertEquals(2, people.size());

            for (var p : people) {
                System.out.printf(p.name);
            }
        });

    }
}

動作確認(Doma 関連の設定が正しいか?)

追加した Doma のコードのビルドや実行を確認します。

クリーンビルドの実行

Eclipse の上部メニューから Project > Clean を実行して問題が発生しないことを確認します。

JUnit の実行

lib プロジェクトを右クリックして Run As > JUnit Test を選択します。
JUnit ビューから PersonDaoTest が実行されていること、グリーンのバーが表示されていることを確認します。

アノテーションプロセッサーによる検証

PersonDao.java の @Insert をコメントアウトし、ファイルを保存します。
エディタ上に下記のエラーメッセージが表示されたらアノテーションプロセッサーが適切に動いていると言えます。

[DOMA4005] The query annotation such as @Select and @Update is required.

確認を終えたらコメントアウトを元に戻してください。

ファイル保存時にアノテーションプロセッサーを起動するには、 Eclipse 上部の Project メニューで Build Automatically が有効になっていなければいけません(デフォルトで有効です)。無効にしている場合は、代わりにクリーンビルドを実行してください。

Q & A

Refresh Gradle Project をいつ実行すればいいのですか?

build.gradle を変更したら実行しましょう。例えば、依存ライブラリを新しく追加したときやライブラリのバージョン番号を変更したときなどです。

ビルドファイルを Groovy ではなく Kotlin DSL で記述する場合の注意点はありますか?

Eclipse や Doma に特化したような注意点は特にないと思います。
Kotlin DSL を使った例はこちらを参照ください。

アノテーションプロセッサーのオプションを指定するにはどうすればいいですか?

次のような記述が必要です。Domaのドキュメントも参照ください。

build.gradle
compileJava {
    aptOptions {
        processorArgs = [
            'doma.debug' : 'true'
        ]
    }
}

アノテーションプロセッサーのオプションは、 Refresh Gradle Project を実施することで Eclipse の設定ファイル(.settings/org.eclipse.jdt.apt.core.prefs)に反映されますが、この設定ファイルは直ちに Eclipse にロードされません。Eclipse 上で有効にするには以下のいずれかの方法を実施してください(もっと良い方法があるかもしれません)。

  • Eclipse を再起動する
  • .settings/org.eclipse.jdt.apt.core.prefs を Eclipse 上で開き修正して保存する(コメント行に空白を1文字追加するなど)

バグレポートを作ってみました。
https://github.com/eclipse/buildship/issues/1305

Eclipse の設定ファイルを確認するにはどうするのが良いですか?

Eclipse の Package Explorer の右上メニューから Filters... を選択し、 .*resources のチェックを外せば Package Explorer 上で表示できます。

Visual Studio Code などで表示するのはオススメしません。Visual Studio Code に Java の拡張機能が入っていると勝手に Eclipse の設定を書き換えたりすることがあるので注意が必要です。

おわりに

もっと良い方法をご存知の方は共有をよろしくお願いします。

Gradle ではなく Maven を利用する場合は、Eclipse + Java + Maven の環境で Doma を動かす を参照ください。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3