Doma CodeGen プラグイン
概要
Doma CodeGenプラグイン は Gradle プラグインです。データベーススキーマから Java、Kotlin、および SQL ファイルを生成します。
主な利点
データベースファーストな開発: 既存のデータベーススキーマから型安全なエンティティクラスとDAOクラスを直接生成
マルチ言語対応: 同じ設定でJavaとKotlinの両方のコードを生成
SQLテンプレート生成: 一般的なREAD操作のSQLテンプレートファイルを自動作成
Testcontainers統合: データベーステストとコード生成でTestcontainersとシームレスに連携
カスタマイズ可能: カスタムテンプレートを使用して生成コードの構造とスタイルを制御
複数データベース対応: PostgreSQL、MySQL、Oracle、H2、その他のJDBC互換データベースに対応
使用例
高速プロトタイピング: データベース設計からデータアクセス層を素早く構築
スキーマ進化: データベーススキーマの変更にあわせてコードを同期
チーム開発: チームメンバー間でエンティティとDAOの実装を一貫性のあるものにする
AntベースのDoma-Genのドキュメントをお探しですか?
AntベースのDoma-Genのドキュメントは、 Doma-Gen GitHub リポジトリ にあります。
AntベースのDoma-Genは現在メンテナンスされていません。代わりにこのページで説明されているDoma CodeGenプラグインを使用してください。
始め方
前提条件
Gradle 8.0 以上
Java 17 以上
データベースへのアクセス(ローカル、リモート、またはTestcontainersベースが可能)
ステップバイステップの設定
プラグインの追加
Doma CodeGenプラグインをGradleビルドファイルに追加します:
plugins { java id("org.domaframework.doma.codegen") version "3.2.2" }
依存関係の設定
必要なJDBCドライバーの依存関係を追加します:
dependencies { // For code generation domaCodeGen("org.postgresql:postgresql:42.7.7") }
ローカルPostgreSQLデータベースのセットアップ
PostgreSQLがローカルにインストールされ実行されていることを確認してください。データベースとテーブルを作成します:
-- Connect to PostgreSQL and create database CREATE DATABASE myapp; -- Switch to the new database and create tables CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, version INTEGER NOT NULL DEFAULT 1, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE orders ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id), total_amount DECIMAL(10,2) NOT NULL, order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, version INTEGER NOT NULL DEFAULT 1 );
コード生成の設定
完全なbuild.gradle.ktsの例:
plugins { java id("org.domaframework.doma.codegen") version "3.2.2" } dependencies { // Code generation dependencies domaCodeGen("org.postgresql:postgresql:42.7.7") } domaCodeGen { val basePackage = "com.example.myapp" register("postgresql") { // Database connection to local PostgreSQL url.set("jdbc:postgresql://localhost:5432/myapp") user.set("postgres") // Replace with your PostgreSQL username password.set("password") // Replace with your PostgreSQL password // Entity generation settings entity { packageName.set("$basePackage.entity") useAccessor.set(true) // Generate getters/setters useListener.set(true) // Generate entity listeners showDbComment.set(true) // Include database comments } // DAO generation settings dao { packageName.set("$basePackage.dao") } } }
コードの生成
コード生成タスクを実行します:
$ ./gradlew domaCodeGenPostgresqlAll
これにより以下が生成されます:
src/main/java/com/example/myapp/entity/にエンティティクラスsrc/main/java/com/example/myapp/dao/にDAOインターフェースsrc/main/resources/META-INF/com/example/myapp/dao/にSQLテンプレートファイルsrc/test/java/com/example/myapp/dao/にテストクラス
生成される内容
コード生成を実行すると、以下のファイルが見つかります:
エンティティクラス
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer id;
public String name;
public String email;
@Version
public Integer version;
@Column(name = "created_at")
public Timestamp createdAt;
}
DAOインターフェース
@Dao
public interface UserDao {
@Select
User selectById(Integer id);
@Insert
Result<User> insert(User entity);
@Update
Result<User> update(User entity);
@Delete
Result<User> delete(User entity);
}
SQLテンプレート
SELECT /*%expand*/* FROM users WHERE id = /* id */1
データベースの例
以下の例では、異なるデータベースタイプの設定方法を示します:
PostgreSQL
dependencies {
domaCodeGen("org.postgresql:postgresql:42.7.7")
}
domaCodeGen {
register("postgresql") {
url.set("jdbc:postgresql://localhost:5432/mydatabase")
user.set("myuser")
password.set("mypassword")
entity {
packageName.set("com.example.postgresql.entity")
}
dao {
packageName.set("com.example.postgresql.dao")
}
}
}
TestcontainersでのPostgreSQL
dependencies {
domaCodeGen(platform("org.testcontainers:testcontainers-bom:1.21.2"))
domaCodeGen("org.postgresql:postgresql:42.7.7")
domaCodeGen("org.testcontainers:postgresql")
}
domaCodeGen {
register("postgresql") {
val initScript = file("src/main/resources/schema-postgresql.sql")
url.set("jdbc:tc:postgresql:15:///test?TC_INITSCRIPT=file:${initScript.absolutePath}")
user.set("test")
password.set("test")
entity {
packageName.set("com.example.postgresql.entity")
}
dao {
packageName.set("com.example.postgresql.dao")
}
}
}
TestcontainersでのMySQL
dependencies {
domaCodeGen(platform("org.testcontainers:testcontainers-bom:1.21.2"))
domaCodeGen("mysql:mysql-connector-java:8.0.33")
domaCodeGen("org.testcontainers:mysql")
}
domaCodeGen {
register("mysql") {
val initScript = file("src/main/resources/schema-mysql.sql")
url.set("jdbc:tc:mysql:8.0:///test?TC_INITSCRIPT=file:${initScript.absolutePath}")
user.set("test")
password.set("test")
entity {
packageName.set("com.example.mysql.entity")
}
dao {
packageName.set("com.example.mysql.dao")
}
}
}
Gradle タスク
Doma CodeGen プラグインは以下のタスクを提供します。
domaCodeGenXxxAll - すべてを生成します。
domaCodeGenXxxDao - DAO ソースファイルを生成します。
domaCodeGenXxxDto - 結果セットのメタデータを読み、DTO ソースファイルを生成します。
domaCodeGenXxxEntity - エンティティソースファイルを生成します。
domaCodeGenXxxSql - SQLファイルを生成します。
domaCodeGenXxxSqlTest - SQL テストソースファイルを生成します。
上記のタスク名の Xxx 部分は、domaCodeGen ブロックの下で定義されているブロック名に置き換えられます。上記の使用例では、Postgresql 部分は postgresql ブロックに対応しています。
定義済みのタスク名をすべて確認するには、tasks タスクを実行します。
$ ./gradlew tasks
設定リファレンス
名前付き設定
domaCodeGen ブロックの下に名前付き設定を定義する必要があります。設定には任意の名前を選択できます。異なるデータベースや環境をサポートするために複数の設定を定義できます。
例:複数データベース設定
domaCodeGen {
register("sales") {
url.set("jdbc:postgresql://localhost:5432/sales")
user.set("sales_user")
password.set("sales_pass")
entity {
packageName.set("com.example.sales.entity")
}
dao {
packageName.set("com.example.sales.dao")
}
}
register("inventory") {
url.set("jdbc:mysql://localhost:3306/inventory")
user.set("inventory_user")
password.set("inventory_pass")
entity {
packageName.set("com.example.inventory.entity")
}
dao {
packageName.set("com.example.inventory.dao")
}
}
}
これによりデータベースごとに個別のタスクセットが生成されます:
$ ./gradlew domaCodeGenSalesAll # Generate all for sales DB
$ ./gradlew domaCodeGenInventoryAll # Generate all for inventory DB
メイン設定オプション
これらのオプションは、各名前付き設定ブロックのトップレベルで設定されます:
オプション |
説明 |
例の値 |
既定値 |
|---|---|---|---|
url |
JDBC connection URL to your database |
|
Required |
user |
Database username for authentication |
|
Required |
password |
Database password for authentication |
|
Required |
dataSource |
Custom data source class (advanced) |
inferred from URL |
|
codeGenDialect |
Database dialect for SQL generation (advanced) |
inferred from URL |
|
catalogName |
テーブルをフィルタリングするデータベースのカタログ名 |
|
|
schemaName |
テーブルをフィルタリングするデータベースのスキーマ名 |
|
|
tableNamePattern |
Regex pattern to include specific tables |
|
|
ignoredTableNamePattern |
Regex pattern to exclude tables |
|
|
tableTypes |
Types of database objects to include |
|
|
versionColumnNamePattern |
Regex to identify version columns |
|
|
languageType |
Target programming language |
|
|
templateDir |
カスタムFreeMarkerテンプレートを含むディレクトリ |
|
|
encoding |
生成されるソースファイルのテキストエンコーディング |
|
|
sourceDir |
生成されたソースファイルの出力ディレクトリ |
|
言語に依存 |
resourceDir |
生成されたSQLファイルの出力ディレクトリ |
|
|
globalFactory |
プラグインの動作をカスタマイズするエントリポイント |
|
エンティティ設定
entity ブロックはエンティティクラスの生成方法を設定します。このブロックは名前付き設定内で定義する必要があります。
基本例
domaCodeGen {
register("sales") {
entity {
packageName.set("com.example.sales.entity")
useAccessor.set(true) // Generate getters/setters
useListener.set(true) // Generate entity listeners
showDbComment.set(true) // Include database comments
prefix.set("Sales") // Add prefix to class names
}
}
}
高度な例
domaCodeGen {
register("enterprise") {
entity {
packageName.set("com.enterprise.domain.entity")
superclassName.set("com.enterprise.core.BaseEntity") // Common base class
listenerSuperclassName.set("com.enterprise.core.BaseEntityListener")
useMetamodel.set(true) // Generate metamodel classes
useMappedSuperclass.set(true) // Use @MappedSuperclass
originalStatesPropertyName.set("originalStates") // Property for @OriginalStates
showTableName.set(false) // Don't show @Table annotations
showColumnName.set(false) // Don't show @Column annotations
}
}
}
オプション |
説明 |
値 |
既定値 |
|---|---|---|---|
overwrite |
生成されたエンティティファイルを上書きするかどうか |
true |
|
overwriteListener |
リスナーを上書きするかどうか |
false |
|
superclassName |
生成されたエンティティクラスに共通のスーパークラス |
||
listenerSuperclassName |
生成されたエンティティリスナークラスに共通のスーパークラス |
||
packageName |
生成されたエンティティクラスのパッケージ名 |
"example.entity" |
|
generationType |
エンティティのIDの生成タイプ |
|
|
namingType |
命名規則 |
|
|
initialValue |
エンティティIDの初期値 |
||
allocationSize |
エンティティIDの割り当てサイズ |
||
showCatalogName |
カタログ名を表示するかどうか |
false |
|
showSchemaName |
スキーマ名を表示するかどうか |
false |
|
showTableName |
テーブル名を表示するかどうか |
true |
|
showColumnName |
カラム名を表示するかどうか |
true |
|
showDbComment |
データベースのコメントを表示するかどうか |
true |
|
useAccessor |
アクセッサーを使うかどうか |
true |
|
useListener |
リスナーを使うかどうか |
true |
|
useMetamodel |
メタモデルを使うかどうか |
true |
|
useMappedSuperclass |
マップされたスーパークラスを使用するかどうか |
true |
|
originalStatesPropertyName |
|
||
entityPropertyClassNamesFile |
エンティティプロパティのクラスの解決に使用されるファイル |
||
prefix |
エンティティクラスの接頭辞 |
||
suffix |
エンティティクラスの接尾辞 |
DAO設定
dao ブロックはDAO(Data Access Object)インターフェースの生成方法を設定します。
基本例
domaCodeGen {
register("sales") {
dao {
packageName.set("com.example.sales.dao")
suffix.set("Repository") // Use "Repository" instead of "Dao"
}
}
}
オプション |
説明 |
値 |
既定値 |
|---|---|---|---|
overwrite |
生成されたDAOファイルを上書きするかどうか |
|
|
packageName |
生成された DAO クラスのパッケージ名 |
"example.dao" |
|
suffix |
Dao クラスの接尾辞 |
"Dao" |
SQL設定
sql ブロックはSQLテンプレートファイルの生成方法を設定します。
domaCodeGen {
register("sales") {
sql {
overwrite.set(true) // Overwrite existing SQL files
}
}
}
注釈
SQLファイルは src/main/resources/META-INF/<package>/dao/ ディレクトリに生成されます。これには selectById.sql や selectByIdAndVersion.sql のような基本的なREAD操作が含まれます。
オプション |
説明 |
値 |
既定値 |
|---|---|---|---|
overwrite |
生成された SQL ファイルを上書きするかどうか |
|
SQLテスト設定
sqlTest ブロックはSQLテストファイルの生成を設定し、テスト用に異なるデータベースを使用できます。
例:個別テストデータベース
domaCodeGen {
register("production") {
// Main database configuration
url.set("jdbc:postgresql://prod-db:5432/myapp")
user.set("prod_user")
password.set("prod_pass")
// Test database configuration
sqlTest {
url.set("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1")
user.set("sa")
password.set("")
}
}
}
例:テスト用同一データベース
domaCodeGen {
register("development") {
url.set("jdbc:tc:postgresql:15:///test")
user.set("test")
password.set("test")
sqlTest {
// Uses same connection as main configuration
// No need to specify url, user, password again
}
}
}
オプション |
説明 |
既定値 |
|---|---|---|
url |
JDBC URL for test database (can be different from main) |
メイン設定と同じ |
user |
Database username for test database |
メイン設定と同じ |
password |
Database password for test database |
メイン設定と同じ |
カスタム設定
Kotlinコードの生成
Kotlin コードを生成するには、languageType オプションに LanguageType.KOTLIN を指定します。
import org.seasar.doma.gradle.codegen.desc.LanguageType
...
domaCodeGen {
register("dev") {
url.set("jdbc:postgresql://localhost:5432/mydatabase")
user.set("myuser")
password.set("mypassword")
languageType.set(LanguageType.KOTLIN)
entity {
packageName.set("org.example.entity")
}
dao {
packageName.set("org.example.dao")
}
}
}
テンプレートのカスタマイズ
Doma CodeGenプラグインは Apache FreeMarker テンプレートを使用してコードを生成します。これらのテンプレートをカスタマイズして、プロジェクトのコーディング規約と要件に合わせることができます。
利用可能なテンプレート
デフォルトのテンプレートファイルは ソースコードリポジトリ にあります。
テンプレートファイル |
目的 |
生成される出力 |
|---|---|---|
entity.ftl |
エンティティクラス生成 |
JPAアノテーション付きのJava/Kotlinエンティティクラス |
entityListener.ftl |
エンティティリスナー生成 |
ライフサイクルコールバック用のエンティティリスナークラス |
dao.ftl |
DAOインターフェース生成 |
基本的なCRUDメソッドを持つDAOインターフェース |
sqlTest.ftl |
SQLテスト生成 |
SQLファイルを検証するテストクラス |
selectById.sql.ftl |
基本的なSELECT SQL |
主キーによる選択のためのSQLファイル |
selectByIdAndVersion.sql.ftl |
楽観的ロックSQL |
バージョンチェック付きの選択のためのSQLファイル |
カスタムテンプレートの設定
テンプレートディレクトリの作成
your-project/ ├── custom-templates/ │ ├── entity.ftl │ ├── dao.ftl │ └── entityListener.ftl └── build.gradle.kts
テンプレートディレクトリの設定
domaCodeGen { register("mydb") { url.set("jdbc:postgresql://localhost:5432/mydb") user.set("user") password.set("pass") templateDir.set(file("$projectDir/custom-templates")) entity { packageName.set("com.example.entity") } dao { packageName.set("com.example.dao") } } }
エンティティテンプレートのカスタマイズ
カスタムアノテーションを追加するために
custom-templates/entity.ftlを作成してください:<#-- Custom entity template with additional annotations --> package ${entityDesc.packageName}; import java.io.Serializable; import org.seasar.doma.*; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Data; /** * Entity for ${entityDesc.tableName} table. <#if entityDesc.comment??> * ${entityDesc.comment}</#if> */ @Entity<#if entityDesc.tableName??>(table = @Table(name = "${entityDesc.tableName}"))</#if> @Data // Lombok annotation @JsonIgnoreProperties(ignoreUnknown = true) // Jackson annotation public class ${entityDesc.simpleName} implements Serializable { <#list entityDesc.propertyDescs as property> <#if property.id> @Id <#if property.generationType??> @GeneratedValue(strategy = GenerationType.${property.generationType}) </#if> </#if> <#if property.version> @Version </#if> <#if property.columnName??> @Column(name = "${property.columnName}") </#if> public ${property.propertyClassName} ${property.propertyName}; </#list> }DAOテンプレートのカスタマイズ
カスタムDAOメソッドのために
custom-templates/dao.ftlを作成してください:<#-- Custom DAO template with additional methods --> package ${daoDesc.packageName}; import org.seasar.doma.*; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Optional; /** * DAO for ${daoDesc.entityDesc.simpleName}. */ @Dao<#if daoDesc.configClassName??>(config = ${daoDesc.configClassName}.class)</#if> @Transactional // Spring transaction annotation public interface ${daoDesc.simpleName} { @Select Optional<${daoDesc.entityDesc.simpleName}> selectById(${daoDesc.entityDesc.idPropertyDesc.propertyClassName} ${daoDesc.entityDesc.idPropertyDesc.propertyName}); @Select List<${daoDesc.entityDesc.simpleName}> selectAll(); @Select List<${daoDesc.entityDesc.simpleName}> selectByExample(${daoDesc.entityDesc.simpleName} example); @Insert Result<${daoDesc.entityDesc.simpleName}> insert(${daoDesc.entityDesc.simpleName} entity); @Update Result<${daoDesc.entityDesc.simpleName}> update(${daoDesc.entityDesc.simpleName} entity); @Delete Result<${daoDesc.entityDesc.simpleName}> delete(${daoDesc.entityDesc.simpleName} entity); @BatchInsert BatchResult<${daoDesc.entityDesc.simpleName}> batchInsert(List<${daoDesc.entityDesc.simpleName}> entities); }
一般的なテンプレート変数
テンプレートでは以下の変数が利用できます:
エンティティテンプレート
entityDesc.packageName- Package name for the entityentityDesc.simpleName- Simple class name (e.g., "User")entityDesc.tableName- Database table nameentityDesc.comment- Table comment from databaseentityDesc.propertyDescs- List of property descriptors
DAOテンプレート
daoDesc.packageName- Package name for the DAOdaoDesc.simpleName- Simple interface name (e.g., "UserDao")daoDesc.entityDesc- Associated entity descriptordaoDesc.configClassName- Doma config class name
プロパティ記述子
property.propertyName- Java property name (e.g., "userId")property.propertyClassName- Java type (e.g., "Integer")property.columnName- Database column nameproperty.id- True if primary keyproperty.version- True if version columnproperty.comment- Column comment from database
高度なテンプレート機能
条件付き生成
<#-- Only generate if table has a version column -->
<#if entityDesc.versionPropertyDesc??>
@Version
public ${entityDesc.versionPropertyDesc.propertyClassName} ${entityDesc.versionPropertyDesc.propertyName};
</#if>
プロパティに基づくカスタムインポート
<#-- Import specific types based on entity properties -->
<#assign hasTimestamp = false>
<#list entityDesc.propertyDescs as property>
<#if property.propertyClassName == "java.sql.Timestamp">
<#assign hasTimestamp = true>
</#if>
</#list>
<#if hasTimestamp>
import java.sql.Timestamp;
</#if>
トラブルシューティング
よくある問題と解決策
問題:「No suitable driver found」エラー
[DOMAGEN0033] The class "org.postgresql.Driver" to which the parameter "driverClassName" refers is not found.
解決策: domaCodeGen 設定にJDBCドライバーの依存関係を追加したことを確認してください:
dependencies {
domaCodeGen("org.postgresql:postgresql:42.7.7")
}
問題:生成されたコードが間違ったパッケージにある
解決策: パッケージ設定を確認してください:
entity {
packageName.set("com.example.entity") // Ensure this is set correctly
}
dao {
packageName.set("com.example.dao") // Ensure this is set correctly
}
問題:カスタムテンプレートが適用されない
解決策: テンプレートディレクトリの構造とファイル名を確認してください:
your-project/
├── template/
│ ├── entity.ftl # Must match exact filename
│ ├── dao.ftl
│ └── entityListener.ftl
└── build.gradle.kts
domaCodeGen {
register("mydb") {
templateDir.set(file("$projectDir/template")) // Point to template directory
}
}
ベストプラクティス
開発にTestcontainersを使用
Testcontainersは異なるマシン間で一貫したデータベース環境を保証します:
// Preferred approach url.set("jdbc:tc:postgresql:15:///test?TC_INITSCRIPT=file:${initScript.absolutePath}")
スキーマファイルにバージョン管理を使用
初期化スクリプトをバージョン管理下に置いてください:
src/main/resources/ ├── schema-postgresql.sql ├── schema-mysql.sql └── test-data.sql
段階的な生成
高速な開発のために特定のタスクを使用してください:
# Generate only entities (faster for schema changes) ./gradlew domaCodeGenMydbEntity # Generate only DAOs (faster for new tables) ./gradlew domaCodeGenMydbDao