PostgreSQL+MyBatis Generator+EclipseでエンティティやSQLの自動生成

# はじめに
MyBatis Generatorではエンティティー、Mapper、SQLを自動生成してくれます。
それにより、テーブルと１対１のエンティティーを自前で生成する必要がなく、とても開発効率があがります。
また、INSERT文、PKをキーとしたUPDATE文、SELECT文も自動で生成してくれます。

テーブルの仕様変更が起こった場合も、カスタマイズ部分には手を加えずに変更部分を反映してくれますので、非常に便利です。

ここでは、PostgreSQL利用時の設定内容についての例を紹介したいと思います。

# 開発環境
* JDK 21
* Eclipse 2024
* PostgreSQL 16
* クラスパスにPostgreSQLのJDBCのjarがあること

# 導入方法
* メニューの「ヘルプ」→「Eclipse マーケットプレイス」を選択
* Eclipse マーケットプレイスのダイアログで、検索欄に「mybatis」を入力して「Enter」キーを押下
* 「MyBatis Generator x.x.x」の「インストール」を押下
![マーケットプレイス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3863714/c0d95bf1-fa33-0df2-9ae8-b91dfe9ea510.png)


# 設定ファイル例
Mybatis Generatorで、各種ファイルを自動生成するには、まずgenerationConfig.xmlを作成し、ファイル生成条件を記述します。

ここでの紹介例は、以下の条件で各ファイルを生成します。
* 指定したパッケージ、フォルダに、全テーブルに対するエンティティー、Mapperを生成
* ～Exampleクラスの生成はしない
* スネークケースのカラム（xxx_yyy形式）はキャメルケース（xxxYyy形式）に変換してマッピング
* INSERT文の自動生成
* PKをキーにSELECTするSQLを自動生成
* PKをキーにUPDATEするSQLを自動生成
* PKをキーにDELETEするSQLを自動生成
* 日付、時刻は、JSR310形式（JDBC Typeとの対応関係は、[公式サイト](https://mybatis.org/generator/configreference/javaTypeResolver.html)を参照）
:::note warn
<b>※注意事項</b>
PostgreSQLの場合、タイムゾーン付きのTimestamp型やTime型の場合、それぞれLocalDateTime,LocalTimeに変換されてしまい、当ジェネレータで生成したソースがうまく動作しません。タイムゾーン付きの日付時刻型を使用する場合は、[こちら](https://qiita.com/charon/items/2ae6518777c48aed541f)の記載の方法により対処する必要があります。
:::


```xml:generationConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
  <context id="PostgresTables" targetRuntime="MyBatis3">

    <!-- スキーマ情報を取得する DB への接続設定 -->
    <jdbcConnection driverClass="org.postgresql.Driver"
        connectionURL="jdbc:postgresql://localhost:5432/sampledb"
        userId="sample"
        password="sample">
    </jdbcConnection>

    <!-- 日付、時刻はJSR310で出力 -->
    <javaTypeResolver>
      <property name="useJSR310Types" value="true" />
    </javaTypeResolver>

    <!-- SELECT 結果等を格納するドメインモデルを生成する設定 -->
    <!-- targetProjectには、プロジェクトフォルダも含めることに注意 -->
    <javaModelGenerator targetPackage="jp.exaple.model" targetProject="sample-project/src/main/java">
      <property name="trimStrings" value="true" />
    </javaModelGenerator>

    <!-- SQL 設定が記述された XML を生成する設定 -->
    <sqlMapGenerator targetPackage="jp.example.repository" targetProject="sample-project/src/main/resources">
    </sqlMapGenerator>
    <!-- マッパークラスを生成する設定 -->
    <javaClientGenerator type="XMLMAPPER" targetPackage="jp.example.repository" targetProject="sample-project/src/main/java">
    </javaClientGenerator>

    <!-- コードを生成するテーブルを指定 -->
	<!-- 全テーブルの場合は"%" -->
    <table schema="public" tableName="%"
        enableSelectByExample="false"
        enableDeleteByExample="false"
    	enableUpdateByExample="false"
        enableCountByExample="false">
		<property name="useActualColumnNames" value="false"  />
    </table>

  </context>
</generatorConfiguration>
```

～Exampleクラスとは、検索条件などをプログラム側で設定することで、SQLに条件を直接書かなくても利用できるようにするための便利クラスなのですが、当方は、SQLで直接条件を書く方が都合がよいため、生成しないようにしています。

INSERT文やUPDATE文は、すべての項目を登録or更新対象とするメソッドと、エンティティーに設定された値のみを登録or更新する（nullの項目は登録or更新しない）ためのメソッドが用意されています。

その他、さまざまなオプションやタグの説明に関しては、公式サイトにあります。

https://mybatis.org/generator/configreference/xmlconfig.html

# 実行方法
* Eclipse上で、generationConfig.xmlファイルを右クリック
* 「実行」→「Mybatis Generator」をクリック

![実行方法.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3863714/9c2f6312-21da-e2b9-b015-7a9d07ffbf82.png)


# 仕様変更でテーブルが変更なった場合の対処
Eclipse版においては、[カスタマイズされた変更部分は上書きされない](https://mybatis.org/generator/running/runningWithEclipse.html)ので、カスタマイズしてても基本的には問題なくMyBatis Generatorを実行できます。（ただし、この部分に関しては一部バグがあるっぽいので後述）
※Eclipse版以外は、オーバーライドするかしないかをオプションで選べる

``generationConfig.xml``ファイルの``<table>``タグに変更対象のテーブル名を記載して実行すれば、カラムの追加や変更に対応したエンティティーやMapper,SQLを生成してくれます。
※カスタマイズした部分に関しては自前で修正の必要があります

# 雑感
SELECT句での使い回しように、全てのカラムが定義された``<sql>``タグが定義されているのですが、この部分に関して、テーブル名修飾が行われていないため、自前で結合文を書きたい場合に使いまわすことが出来ないのが若干不便だなと思いました。
テーブル名修飾してくれれば、あらゆるところから利用できるようになるので、仕様変更にも容易に対応できますし。

あと、テーブルの仕様変更で再実行した際、Mapperクラスで新たに定義したメソッドが一つ欠落するという事象が発生しました。その事象が発生したのは１クラスのみだったためさほど影響はありませんでしたが。
基本的にはカスタマイズした部分の上書きしないはずなのですが、一部バグがあるみたいなので注意が必要です。
SQL定義用XMLファイルに関しては問題なかったので、Mapperクラスの欠落を補うだけで問題は解決しましたが、ちょっと注意が必要です。

とはいえ、エンティティーに関しては、カスタマイズすることはないと思われるので、仕様変更時、エンティティーだけでも再実行して対応するのは有用かと思いました。

なお、自動生成した部分は一切カスタマイズ不可、という方針にすれば、安心して何度も実行することが出来ます。