takeda_san’s blog

KotlinとVRを頑張っていく方向。

doma-codegen-pluginを触ってみる

概要

doma-codegen-plugin とはデータベースのテーブル定義からEntityを生成してくれる素敵なgradleプラグイン
今回はこのプラグインを動かしてどんなコードができるのか確認してみます。

github.com

便利なサンプルリポジトリ

doma-codegen-plugin入りのKotlin向けのDOMAサンプルリポジトリが既にあるので、それを使っていきます。
サンプルでDBまわりの設定とテーブル定義のスクリプトも完備。
あとはビルドするだけです。

github.com

まずはお試し

細かくドキュメントを見ていく前にせっかく動くサンプルがあるので、確認をしてみる。

とりあえず生成してみよう

READMEに従って、まずはコードの生成をしてみる。

./gradlew domaCodeGenDevEntity

ビルド後変化があったファイル。
ちゃんと、Kotlinで生成されている。
既に存在するentityファイルが再生成された模様。

f:id:takeda_san:20210301231524p:plain

生成されたコードを見てみよう

2つあるテーブルのうちdepartmentから見てみる。

create table department(
    id int not null identity primary key,
    name varchar(20),
    version int not null
);

生成されたコードはこちら。

@Entity(listener = DepartmentListener::class, metamodel = Metamodel())
@Table(name = "DEPARTMENT")
class Department : AbstractDepartment() {

    /**  */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    var id: Int = -1

    /**  */
    @Column(name = "NAME")
    var name: Name? = null

    /**  */
    @Version
    @Column(name = "VERSION")
    var version: Int = -1
}

Table名のアノテーションはもちろんのこと、VERSIONやIDもちゃんと設定されている。
DomaのDomain定義(Nameの型)も設定されている。
(どこで設定しているんだ…?)

domaCodeGen設定を見ていく

動作はわかったので、なぜこうなるのかを設定を見ながら確認していく。

config

pluginの方のREADMEを見ると、plugin自体の設定もbuild.gradle.ktsに記入するらしい。

GitHub - domaframework/doma-codegen-plugin: Generates Java, Kotlin, and SQL files from Database

今回のサンプルだとこの辺。

domaCodeGen {
    register("dev") {
        url.set(h2Url)
        user.set(h2User)
        password.set(h2Password)
        languageType.set(org.seasar.doma.gradle.codegen.desc.LanguageType.KOTLIN)
        entity {
            packageName.set("sample.entity")
            val mappingFile = layout.projectDirectory.file("$projectDir/codegen-name-mapping.properties")
            entityPropertyClassNamesFile.set(mappingFile)
        }
    }
}

configの一覧はこの辺。

GitHub - domaframework/doma-codegen-plugin: Generates Java, Kotlin, and SQL files from Database

DBへの接続情報諸々。
実際にDB内の定義を見て生成しているらしい。
(つまり作成用のスクリプトがなくてもDB現物があればEntityが作れる・・・?)

url.set(h2Url)
user.set(h2User)
password.set(h2Password)

このlanguageTypeの設定でKotlin/Javaを切り替えている模様。

languageType.set(org.seasar.doma.gradle.codegen.desc.LanguageType.KOTLIN)

試しにJavaに変更して、再生成してみる。

languageType.set(org.seasar.doma.gradle.codegen.desc.LanguageType.JAVA)

f:id:takeda_san:20210302000824p:plain

javaディレクトリ配下にentity一式が生成された。

entityの設定

domaCodeGenのentityブロックを見ていく。

entity {
    packageName.set("sample.entity")
    val mappingFile = layout.projectDirectory.file("$projectDir/codegen-name-mapping.properties")
    entityPropertyClassNamesFile.set(mappingFile)
}

設定の一覧はこの辺。

GitHub - domaframework/doma-codegen-plugin: Generates Java, Kotlin, and SQL files from Database

生成先のパッケージ名の設定。

packageName.set("sample.entity")

ここでDomaのDomainの設定がされている様子。

val mappingFile = layout.projectDirectory.file("$projectDir/codegen-name-mapping.properties")
entityPropertyClassNamesFile.set(mappingFile)

参照されている、codegen-name-mapping.properties はこんな感じ。

gender=sample.domain.Gender
name=sample.domain.Name

左辺と同じ名前なら、ここで設定されているClassがdomainと紐づけられる…ということだろうか。
試しにちょっとnameの方の定義を変えてみる。

gender=sample.domain.Gender
name__=sample.domain.Name

生成されたコードの該当箇所がこちら。

@Column(name = "NAME")
- var name: Name? = null
+ var name: String? = null

この通り、型がStringに変更された。
推測通りで間違いなさそう。
(逆に言うと同じDomainは同名にする必要があるのかな・・・?)

他にも設定を見る限りListenerや基底クラス生成が不要な場合、設定変更で対応できるっぽい。

触ってみた感想

DTO的なEntityの生成ツールは、いくつか種類があるけれどもDomaを使っている場合はこれ一択な気がします。
コード自体は毎回洗い替えというか、生成しなおした方がシンプルなのでDB上の定義以外のドメインロジックは別のEntityとして持った方が取り回しが良さそうです。