1
0

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

Last updated at Posted at 2024-06-01

はじめに

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

前提

バージョンなど

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

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

  • Eclipse IDE for Java Developers 2024-03 (4.31.0)
  • Java 17.0.10(Eclipse のデフォルト)
  • Maven 3.9.6(Eclipse のデフォルト)
  • Doma 2.60.0

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

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

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

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

Eclipse から Maven Project の作成

Eclipse 上部のメニューから File > New > Maven Project を選択しダイアログを開きます。
Create a simple project にチェックを入れ、 Next ボタンを押します。
Group Id と Artifact Id のどちらにも example を入れ、Finish ボタンを押します。

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

Annotation Processing の有効化

example プロジェクトを右クリックして Properties > Maven > Annotaion Processing を選択し、 Enable Project specific settings にチェックを入れ、 Automatically configure JDT APT にもチェックを入れます。

Properties_for_example.png

この設定を有効にしないと、pom.xml から .factorypath など Eclipseのアノテーションプロセッシングに必要なファイルが生成されません。必ず有効にしましょう。

生成された pom.xml の確認

example プロジェクトの pom.xml を確認しましょう。

pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>example</groupId>
  <artifactId>example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</project>

pom.xml の修正

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

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>example</groupId>
    <artifactId>example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  
    <properties>
        <doma.version>2.60.0</doma.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.seasar.doma</groupId>
            <artifactId>doma-core</artifactId>
            <version>${doma.version}</version>
        </dependency>
        <dependency>
            <groupId>org.seasar.doma</groupId>
            <artifactId>doma-slf4j</artifactId>
            <version>${doma.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.11</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>2.2.224</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.10.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.10.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>17</source> <!-- depending on your project -->
                    <target>17</target> <!-- depending on your project -->
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.seasar.doma</groupId>
                            <artifactId>doma-processor</artifactId>
                            <version>${doma.version}</version>
                        </path>
                    </annotationProcessorPaths>
                    <compilerArgs>
                        <!-- if you are using a Maven project in Eclipse, this argument is required -->
                        <arg>-Adoma.resources.dir=${project.basedir}/src/main/resources</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

ポイントは、 compilerArgs にリソースフォルダを指定することです。これは、注釈処理時にSQLファイルを参照するために必要です。

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

example プロジェクトの 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);
}

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

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

example プロジェクトの 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 の実行

example プロジェクトを右クリックして 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

Maven > Update Project をいつ実行すればいいのですか?

明示的にこのコマンドを実行しなくてもデフォルトで pom.xml の変更が自動的にプロジェクトに反映されるようですが、必要に応じて、プロジェクトや pom.xml を右クリックして Maven > Update Project を実行してください。

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

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

pom.xml
<compilerArgs>
    <arg>-Adoma.resources.dir=${project.basedir}/src/main/resources</arg>
    <arg>-Adoma.dao.subpackage=impl</arg>
    <arg>-Adoma.dao.suffix=Impl</arg>
</compilerArgs>

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

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

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

おわりに

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

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

1
0
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
0