doma-genでDBのテーブルをJavaのEntityクラスに自動生成

# 概要
当記事ではローカルのデータベースへアクセスして、DB中のテーブルをJavaのEntityクラスとして自動生成する方法を説明する。
- プロジェクト：`SpringBoot mavenプロジェクト`
- 利用ライブラリ/とツール
  - Eclipse：`2023`
  - java：`17`
  - mysql：`5.8`
- 参照リンク
  - https://doma.seasar.org/extension/doma_gen.html
  - https://doma-gen.readthedocs.io/en/2.7.0/gen/

※　Doma-genでDao、SQLファイルも自動生成できるが当記事では割愛する。


# 設定方法
### pom.xmlの修正
- 以下のライブラリを使用するのでimportしておく必要がある
```xml
		<!-- https://mvnrepository.com/artifact/org.seasar.doma/doma -->
		<dependency>
			<groupId>org.seasar.doma</groupId>
			<artifactId>doma</artifactId>
			<version>2.29.0</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.seasar.doma/doma-gen -->
		<dependency>
			<groupId>org.seasar.doma</groupId>
			<artifactId>doma-gen</artifactId>
			<version>2.28.0</version>
		</dependency>
```
### 必要なJarファイルを用意する
- `./lib`の配下に以下のJarファイルを保存しておく。
  * [doma-gen-2.28.0.jar](https://mvnrepository.com/artifact/org.seasar.doma/doma-gen)
  * [freemarker-2.3.32.jar](https://mvnrepository.com/artifact/org.freemarker/freemarker/2.3.32)
  * [mysql-connector-j-8.1.0.jar](https://dev.mysql.com/downloads/connector/j/?os=26)

### テンプレート作成
- `./doma-gen-template`の配下に`entity.ftl`を作成する
- 当ファイルは必要に応じて作成すればよい、必須ではない。
- 作成したファイルを`doma-gen-build.xml`でimportして使う。

```
<#-- このテンプレートに対応するデータモデルのクラスは org.seasar.doma.extension.gen.EntityDesc です -->
<#import "/lib.ftl" as lib>
<#if lib.copyright??>
${lib.copyright}
</#if>
<#if packageName??>
package ${packageName};
</#if>

<#list importNames as importName>
import ${importName};
</#list>

/**
<#if showDbComment && comment??>
 * ${comment}
</#if>
<#if lib.author??>
 * @author ${lib.author}
</#if>
 */
@Entity<#if useListener || namingType != "NONE">(</#if><#if useListener>listener = ${listenerClassSimpleName}.class</#if><#if namingType != "NONE"><#if useListener>, </#if>naming = ${namingType.referenceName}</#if><#if useListener || namingType != "NONE">)</#if>
<#if showCatalogName && catalogName?? || showSchemaName && schemaName?? || showTableName && tableName??>
@Table(<#if showCatalogName && catalogName??>catalog = "${catalogName}"</#if><#if showSchemaName && schemaName??><#if showCatalogName && catalogName??>, </#if>schema = "${schemaName}"</#if><#if showTableName><#if showCatalogName && catalogName?? || showSchemaName && schemaName??>, </#if>name = "${tableName}"</#if>)
</#if>
public class <#if entityPrefix??>${entityPrefix}</#if>${simpleName}<#if entitySuffix??>${entitySuffix}</#if><#if superclassSimpleName??> extends ${superclassSimpleName}</#if> {
<#list ownEntityPropertyDescs as property>

  <#if showDbComment && property.comment??>
    /** ${property.comment} */
  <#else>
    /** */
  </#if>
  <#if property.id>
    @Id
    <#if property.generationType??>
    @GeneratedValue(strategy = ${property.generationType.referenceName})
      <#if property.generationType == "SEQUENCE">
    @SequenceGenerator(sequence = "${tableName}_${property.columnName}"<#if property.initialValue??>, initialValue = ${property.initialValue}</#if><#if property.allocationSize??>, allocationSize = ${property.allocationSize}</#if>)
      <#elseif property.generationType == "TABLE">
    @TableGenerator(pkColumnValue = "${tableName}_${property.columnName}"<#if property.initialValue??>, initialValue = ${property.initialValue}</#if><#if property.allocationSize??>, allocationSize = ${property.allocationSize}</#if>)
      </#if>
    </#if>
  </#if>
  <#if property.version>
    @Version
  </#if>
  <#if property.showColumnName && property.columnName??>
    @Column(name = "${property.columnName}")
  </#if>
    <#if !useAccessor>public </#if>${property.propertyClassSimpleName} ${property.name};
</#list>
<#if originalStatesPropertyName??>

    /** */
    @OriginalStates
    <#if entityPrefix??>${entityPrefix}</#if>${simpleName}<#if entitySuffix??>${entitySuffix}</#if> ${originalStatesPropertyName};
</#if>
<#if useAccessor>
  <#list ownEntityPropertyDescs as property>

    /** 
     * Returns the ${property.name}.
     * 
     * @return the ${property.name}
     */
    public ${property.propertyClassSimpleName} get${property.name?cap_first}() {
        return ${property.name};
    }

    /** 
     * Sets the ${property.name}.
     * 
     * @param ${property.name} the ${property.name}
     */
    public void set${property.name?cap_first}(${property.propertyClassSimpleName} ${property.name}) {
        this.${property.name} = ${property.name};
    }
  </#list>
</#if>
}
```

### データ型をカスタマイズするクラスを作成
- Doma-genで設定しているデフォルトのデータ型以外のものを使用したい場合用意する
- 特に時間、配列などの項目を設定するときに使う
- 作成したファイルを`doma-gen-build.xml`でimportして使う。
- `org.seasar.doma.extension.gen.dialect.OracleGenDialect`を継承する必要がある。

```java
import java.sql.Date;
import java.sql.Timestamp;

import org.seasar.doma.extension.gen.ClassConstants;
import org.seasar.doma.extension.gen.dialect.OracleGenDialect;

public class DemoOralceGenDialect extends OracleGenDialect {

	public void DemoOralceGenDialect() {
		classNameMap.put("date", Date.class.getName());
	}

}
```

### doma-gen-build.xmlの作成

```xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="doma-gen-example" default="gen" basedir=".">
	<property name="javaDestDir" value="src/main/java" />
　　<!--データ型をカスタマイズするクラスを作成で作成したクラス-->
	<property name="genDialectClassName"
		value="com.example.domagen.DemoOralceGenDialect" />
　　<!--DB接続情報、ここではMysql-->
　　<property name="dialectName" value="mysql" />
	<property name="driverClassName" value="com.mysql.jdbc.Driver" />
	<property name="url" value="jdbc:mysql://localhost:3306/xxx" />
	<property name="user" value="sa" />
	<property name="password" value="password" />
    <!--テンプレート作成で作成したテンプレートファイル-->
	<property name="domaGenTemplate" value="doma-gen-template" />
    <!--Entity出力するパッケージ-->
	<property name="entityPackageName" value="com.example.entity" />

    <!--Jarファイルを読み取り-->
	<path id="classpath">
		<fileset dir="lib" />
		<pathelement location="./target/classes" />
	</path>

	<taskdef name="gen"
		classname="org.seasar.doma.extension.gen.task.Gen"
		classpathref="classpath" loaderref="loader" />
	<typedef name="
		entityConfig "
		classname="org.seasar.doma.extension.gen.task.EntityConfig"
		loaderref="loader" />

	<target name="gen">
	<gen genDialectClassName="${genDialectClassName}"
		dialectName="${dialectName}" driverClassName="${driverClassName}"
		url="${url}" user="${user}" password="${password}"
		ignoredTableNamePattern="^XXX" tableNamePattern="^YYY"
		templatePrimaryDir="domaGenTemplate" >
		<entityConfig destdir="${javaDestDir}"
			packageName="${entityPackageName}" useListener="false" />
	</gen>
</target>
</project>
```

## 自動生成の実行
- `doma-gen-build`を右クリック→`実行`→`外部ツールの構成`
- `Antビルド`を右クリック → `新規`→ "実行"