Java - Visual Studio CodeでDomaの注釈処理を使う

Visual Studio CodeDomaの注釈処理を使ってDao付近を自動生成したくて調べたが、情報がなさそうだったので書く。

環境

やり方

事前準備

自動生成が動くにはorg.eclipse.buildship.core.prefsが生成されている必要があるようだ。
このファイルの中身はbuild.gradleの依存関係がインポートされる際に生成されるが、インポートの時点でファイルがなかったり空ファイルだったりした場合は中身の生成がスキップされてしまい、その後のソースの自動生成も反応してくれない。
このため、最初にファイルを作成し以下2行を記載しておく。

.settings/org.eclipse.buildship.core.prefs
connection.project.dir=
eclipse.preferences.version=1

注釈処理の有効化

Visual Studio CodeでGradleを使って注釈処理するという内容は以下リンクにて言及されていた。
これを参考にDomaも扱えるようにする。
Is Annotation Processing Supported for Gradle project? · Issue #1039 · redhat-developer/vscode-java · GitHub

注釈処理の依存関係を追加

build.gradle
plugins {
  id 'org.springframework.boot' version '2.7.4'
  id 'io.spring.dependency-management' version '1.0.14.RELEASE'
  id 'java'
  id 'war'
+ // 注釈処理
+ id 'com.diffplug.eclipse.apt' version '3.39.0'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
  mavenCentral()
}

dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
  implementation 'org.springframework.boot:spring-boot-starter-web'
  runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
  providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
  testImplementation 'org.springframework.boot:spring-boot-starter-test'

  compileOnly 'org.projectlombok:lombok'
  annotationProcessor 'org.projectlombok:lombok'

+ // doma関連
+ implementation 'org.seasar.doma:doma-core:2.53.1'
+ implementation 'org.seasar.doma.boot:doma-spring-boot-starter:1.6.0'
+ annotationProcessor 'org.seasar.doma:doma-processor:2.53.1'
}

+ // 自動生成ファイルの出力先ディレクトリ
+ eclipse {
+   jdt {
+     apt {
+       genSrcDir = file('src-gen/main/java')
+       genTestSrcDir = file('src-gen/test/java')
+     }
+   }
+ }

+ // SQLテンプレートのコピータスク
+ task _copySqls(type: Copy) {
+   from 'src/main/resources/META-INF'
+   into 'bin/default/META-INF'
+ }

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

設定ファイル生成

以下のビルドタスクを実行して設定ファイルを生成する。

  • eclipseJdtApt
  • eclipseJdt
  • eclipseFactorypath

Visual Studio Codeを再起動

再起動するとビルドタスクで自動生成ファイルの出力先として指定したディレクトリ(src-gen)が作成される。

Gradleのリフレッシュ

手元の環境ではこれをやらないと自動生成してくれなかった。
build.gradleに空行を足して保存すれば、依存関係を追記した際のように同期するかを聞いてくるのでyesすればよい。

自動生成の動作確認

ここまでの手順がうまくいっていれば、以下のファイルを作成すると同時にsrc-genディレクトリの配下に_Employee.javaが自動生成されるはず。

src/main/java/com/example/demo/Employee.java
package com.example.demo;

import org.seasar.doma.*;
import lombok.Data;

@Entity
@Data
public class Employee {
  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE)
  @SequenceGenerator(sequence = "EMPLOYEE_SEQ")
  Integer id;

  String name;
}

サンプルプロジェクト

自動生成されたクラスを使って実際に動作するサンプルとして、http://localhost:8080/employees で待機し、employeeテーブルの内容をJSON形式で応答するAPIを作成してみる。
Spring Bootで新規プロジェクトを作り、この記事のソースをコピペすれば動くはず。

DBを作る

CREATE OR REPLACE DATABASE testdb1;
CREATE OR REPLACE TABLE employee (
  id int not null auto_increment primary key,
  name varchar(255)
);

INSERT INTO employee VALUE (1, 'Lorem ipsum');
INSERT INTO employee VALUE (2, 'dolor sit');
INSERT INTO employee VALUE (3, 'amet consectetur');
INSERT INTO employee VALUE (4, 'adipiscing elit');

SELECT * FROM employee;

ソース類を書く

作成するソースは以下の通り。

  • application.properties
  • Employee.java (自動生成の動作確認で作成したもの)
  • EmployeeDao.java
  • EmployeeController.java
  • all.sql
src/main/resources/application.properties
spring.datasource.url=jdbc:mariadb://mariadb:3306/testdb1
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driverClassName=org.mariadb.jdbc.Driver
src/main/java/com/example/demo/EmployeeDao.java
package com.example.demo;

import java.util.List;
import org.seasar.doma.*;
import org.seasar.doma.boot.ConfigAutowireable;

// @ConfigAutowireableを付けておくと、
// Implを自動生成した際に@Repositoryを付加しておいてくれる。
@Dao
@ConfigAutowireable
public interface EmployeeDao {
  @Select
  List<Employee> all();
}

EmployeeDaoを作成するとall()メソッドでエラーになるが、いったんそのまま進める。
この手順の最後でSQLファイルをbin配下にコピーすることで解消できる。

src/main/java/com/example/demo/EmployeeController.java
package com.example.demo;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

@RestController
public class EmployeeController {

  @Lazy
  @Autowired
  private EmployeeService service;

  @GetMapping("/employees")
  public List<Employee> index() throws Exception {
    return service.list();
  }

  @Service
  public class EmployeeService {
    @Autowired
    EmployeeDao dao;

    public List<Employee> list() throws Exception {
      return dao.all();
    }
  }
}
src/main/resources/META-INF/com/example/demo/EmployeeDao/all.sql
SELECT
  /*%expand*/*
FROM
  employee
ORDER BY
  id

SQLファイルをbin配下へコピーする

以下のビルドタスクでSQLファイルをbin配下へコピーする。

  • _copySqls

タスク実行後、EmployeeDaoを再コンパイルするとエラーが解消する。


これでRun and Debugからサーバ起動すれば動くはず。

参考リンク

*1:MariaDBはサンプルプロジェクトで利用