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 or higher
Java 17 or higher
Access to a database (can be local, remote, or Testcontainers-based)
ステップバイステップの設定
Add the Plugin
Doma CodeGenプラグインをGradleビルドファイルに追加します:
plugins { java id("org.domaframework.doma.codegen") version "3.2.0" }
Configure Dependencies
必要なJDBCドライバーの依存関係を追加します:
dependencies { // For code generation domaCodeGen("org.postgresql:postgresql:42.7.7") }
Set up Local PostgreSQL Database
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 );
Configure Code Generation
完全なbuild.gradle.ktsの例:
plugins { java id("org.domaframework.doma.codegen") version "3.2.0" } 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") } } }
Generate Code
コード生成タスクを実行します:
$ ./gradlew domaCodeGenPostgresqlAll
これにより以下が生成されます:
Entity classes in
src/main/java/com/example/myapp/entity/DAO interfaces in
src/main/java/com/example/myapp/dao/SQL template files in
src/main/resources/META-INF/com/example/myapp/dao/Test classes in
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 テストソースファイルを生成します。
Note that the Xxx part in each task name is replaced with the block name defined under the domaCodeGen block.
In the usage example above, the Postgresql part corresponds to the postgresql block.
定義済みのタスク名をすべて確認するには、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
メイン設定オプション
これらのオプションは、各名前付き設定ブロックのトップレベルで設定されます:
オプション |
説明 |
Example Values |
既定値 |
|---|---|---|---|
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 |
Database catalog name to filter tables |
|
|
schemaName |
Database schema name to filter tables |
|
|
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 |
Directory containing custom FreeMarker templates |
|
|
encoding |
Text encoding for generated source files |
|
|
sourceDir |
Output directory for generated source files |
|
depends on language |
resourceDir |
Output directory for generated SQL files |
|
|
globalFactory |
プラグインの動作をカスタマイズするエントリポイント |
[2] 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の生成タイプ |
[3] GenerationType の列挙値 |
|
namingType |
命名規則 |
[4] NamingType の列挙値 |
|
initialValue |
エンティティIDの初期値 |
||
allocationSize |
エンティティIDの割り当てサイズ |
||
showCatalogName |
カタログ名を表示するかどうか |
false |
|
showSchemaName |
スキーマ名を表示するかどうか |
false |
|
showTableName |
テーブル名を表示するかどうか |
true |
|
showColumnName |
カラム名を表示するかどうか |
true |
|
showDbComment |
データベースのコメントを表示するかどうか |
true |
|
useAccessor |
アクセッサーを使うかどうか |
true |
|
useListener |
リスナーを使うかどうか |
true |
|
useMetamodel |
メタモデルを使うかどうか |
true |
|
useMappedSuperclass |
マップされたスーパークラスを使用するかどうか |
true |
|
originalStatesPropertyName |
@OriginalStates アノテーションが付けられるプロパティ |
||
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 files are generated in src/main/resources/META-INF/<package>/dao/ directory.
These include basic READ operations like selectById.sql and selectByIdAndVersion.sql.
オプション |
説明 |
値 |
既定値 |
|---|---|---|---|
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) |
Same as main configuration |
user |
Database username for test database |
Same as main configuration |
password |
Database password for test database |
Same as main configuration |
カスタム設定
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ファイル |
カスタムテンプレートの設定
Create Template Directory
your-project/ ├── custom-templates/ │ ├── entity.ftl │ ├── dao.ftl │ └── entityListener.ftl └── build.gradle.kts
Configure Template Directory
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") } } }
Customize Entity Template
カスタムアノテーションを追加するために
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> }Customize DAO Template
カスタム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
}
}
ベストプラクティス
Use Testcontainers for Development
Testcontainersは異なるマシン間で一貫したデータベース環境を保証します:
// Preferred approach url.set("jdbc:tc:postgresql:15:///test?TC_INITSCRIPT=file:${initScript.absolutePath}")
Use Version Control for Schema Files
初期化スクリプトをバージョン管理下に置いてください:
src/main/resources/ ├── schema-postgresql.sql ├── schema-mysql.sql └── test-data.sql
Incremental Generation
高速な開発のために特定のタスクを使用してください:
# Generate only entities (faster for schema changes) ./gradlew domaCodeGenMydbEntity # Generate only DAOs (faster for new tables) ./gradlew domaCodeGenMydbDao