コンテンツにスキップ

MyBatis Generator の設定⚓︎

infrastructure プロジェクトにおいて、 MyBatis Generator を利用してエンティティやマッパーインターフェース、 SQL マッピングファイルを自動的に生成するための設定について解説します。

事前準備⚓︎

本手順を実行する前に infrastructure プロジェクトの設定 を完了してください。

MyBatis Generator を実行する際は、生成対象となるテーブルが作成されたデータベースを稼働させる必要があります。 本設定では H2 Console を利用して H2 Database に以下の DDL と DML を実行し、テーブルを作成しています。

サンプルアプリケーションの schema.sql
schema.sql
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
DROP TABLE IF EXISTS assets CASCADE;
CREATE TABLE assets
(
  id BIGSERIAL NOT NULL PRIMARY KEY, -- primary key column
  asset_code VARCHAR(32) NOT NULL,
  asset_type VARCHAR(128) NOT NULL
);

DROP TABLE IF EXISTS baskets CASCADE;
CREATE TABLE baskets
(
  id BIGSERIAL NOT NULL PRIMARY KEY, -- primary key column
  buyer_id VARCHAR(64) NOT NULL
);

DROP TABLE IF EXISTS catalog_brands CASCADE;
CREATE TABLE catalog_brands
(
  id BIGSERIAL NOT NULL PRIMARY KEY, -- primary key column
  name VARCHAR(128) NOT NULL
);

DROP TABLE IF EXISTS catalog_categories CASCADE;
CREATE TABLE catalog_categories
(
  id BIGSERIAL NOT NULL PRIMARY KEY, -- primary key column
  name VARCHAR(128) NOT NULL
);

DROP TABLE IF EXISTS orders CASCADE;
CREATE TABLE orders
(
  id BIGSERIAL NOT NULL PRIMARY KEY, -- primary key column
  buyer_id VARCHAR(64) NOT NULL,
  order_date TIMESTAMP WITH TIME ZONE NOT NULL,
  ship_to_full_name VARCHAR(64) NOT NULL,
  ship_to_postal_code VARCHAR(16) NOT NULL,
  ship_to_todofuken VARCHAR(16) NOT NULL,
  ship_to_shikuchoson VARCHAR(32) NOT NULL,
  ship_to_azana_and_others VARCHAR(128) NOT NULL,
  consumption_tax_rate NUMERIC(18,6) NOT NULL,
  total_items_price NUMERIC(18,6) NOT NULL,
  delivery_charge NUMERIC(18,6) NOT NULL,
  consumption_tax NUMERIC(18,6) NOT NULL,
  total_price NUMERIC(18,6) NOT NULL
);

DROP TABLE IF EXISTS basket_items CASCADE;
CREATE TABLE basket_items
(
  id BIGSERIAL NOT NULL PRIMARY KEY, -- primary key column
  basket_id BIGINT NOT NULL,
  catalog_item_id BIGINT NOT NULL,
  unit_price NUMERIC(18,6) NOT NULL,
  quantity INT NOT NULL,
  CONSTRAINT FK_basket_items_baskets FOREIGN KEY (basket_id) REFERENCES baskets(id) ON DELETE CASCADE
);

DROP TABLE IF EXISTS catalog_items CASCADE;
CREATE TABLE catalog_items
(
  id BIGSERIAL NOT NULL PRIMARY KEY, -- primary key column
  name VARCHAR(512) NOT NULL,
  description VARCHAR NOT NULL,
  price NUMERIC(18,6) NOT NULL,
  product_code VARCHAR(128) NOT NULL,
  catalog_category_id BIGINT NOT NULL,
  catalog_brand_id BIGINT NOT NULL,
  is_deleted BOOLEAN NOT NULL,
  row_version TIMESTAMP WITH TIME ZONE NOT NULL,
  CONSTRAINT FK_catalog_items_catalog_brands FOREIGN KEY (catalog_brand_id) REFERENCES catalog_brands(id) ON DELETE CASCADE,
  CONSTRAINT FK_catalog_items_catalog_categories FOREIGN KEY (catalog_category_id) REFERENCES catalog_categories(id) ON DELETE CASCADE
);

DROP TABLE IF EXISTS order_items CASCADE;
CREATE TABLE order_items
(
  id BIGSERIAL NOT NULL PRIMARY KEY, -- primary key column
  ordered_catalog_item_id BIGINT NOT NULL,
  ordered_product_name VARCHAR(512) NOT NULL,
  ordered_product_code VARCHAR(128) NOT NULL,
  unit_price NUMERIC(18,6) NOT NULL,
  quantity INT NOT NULL,
  order_id BIGINT NOT NULL,
  CONSTRAINT FK_order_items_orders FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE
);

DROP TABLE IF EXISTS catalog_item_assets CASCADE;
CREATE TABLE catalog_item_assets
(
  id BIGSERIAL NOT NULL PRIMARY KEY, -- primary key column
  asset_code VARCHAR(32) NOT NULL,
  catalog_item_id BIGINT NOT NULL,
  CONSTRAINT FK_catalog_item_assets_catalog_items FOREIGN KEY (catalog_item_id) REFERENCES catalog_items(id) ON DELETE CASCADE
);
サンプルアプリケーションの data.sql
data.sql
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
INSERT INTO assets (asset_code, asset_type)
VALUES 
    ('b52dc7f712d94ca5812dd995bf926c04', 'png'),
    ('80bc8e167ccb4543b2f9d51913073492', 'png'),
    ('05d38fad5693422c8a27dd5b14070ec8', 'png'),
    ('45c22ba3da064391baac91341067ffe9', 'png'),
    ('4aed07c4ed5d45a5b97f11acedfbb601', 'png'),
    ('082b37439ecc44919626ba00fc60ee85', 'png'),
    ('f5f89954281747fa878129c29e1e0f83', 'png'),
    ('a8291ef2e8e14869a7048e272915f33c', 'png'),
    ('66237018c769478a90037bd877f5fba1', 'png'),
    ('d136d4c81b86478990984dcafbf08244', 'png'),
    ('47183f32f6584d7fb661f9216e11318b', 'png'),
    ('cf151206efd344e1b86854f4aa49fdef', 'png'),
    ('ab2e78eb7fe3408aadbf1e17a9945a8c', 'png'),
    ('0e557e96bc054f10bc91c27405a83e85', 'png'),
    ('e622b0098808492cb883831c05486b58', 'png');

INSERT INTO catalog_brands (id, name) 
VALUES 
    (1, '高級なブランド'),
    (2, 'カジュアルなブランド'),
    (3, 'ノーブランド');
ALTER TABLE catalog_brands ALTER COLUMN id RESTART WITH 4;

INSERT INTO catalog_categories (id, name) 
VALUES 
    (1, '服'),
    (2, 'バッグ'),
    (3, 'シューズ');
ALTER TABLE catalog_categories ALTER COLUMN id RESTART WITH 4;

INSERT INTO catalog_items (id, name, description, price, product_code, catalog_category_id, catalog_brand_id, is_deleted, row_version) 
VALUES 
    (1, 'クルーネック Tシャツ - ブラック', '定番の無地ロングTシャツです。', 1980, 'C000000001', 1, 3, false, CURRENT_TIMESTAMP),
    (2, '裏起毛 スキニーデニム', '暖かいのに着膨れしない起毛デニムです。', 4800, 'C000000002', 1, 2, false, CURRENT_TIMESTAMP),
    (3, 'ウールコート', 'あたたかく肌ざわりも良いウール100%のロングコートです。', 49800, 'C000000003', 1, 1, false, CURRENT_TIMESTAMP),
    (4, '無地 ボタンダウンシャツ', 'コットン100%の柔らかい着心地で、春先から夏、秋口まで万能に使いやすいです。', 2800, 'C000000004', 1, 2, false, CURRENT_TIMESTAMP),
    (5, 'レザーハンドバッグ', 'コンパクトサイズのバッグですが収納力は抜群です。', 18800, 'B000000001', 2, 3, false, CURRENT_TIMESTAMP),
    (6, 'ショルダーバッグ', 'エイジング加工したレザーを使用しています。', 38000, 'B000000002', 2, 2, false, CURRENT_TIMESTAMP),
    (7, 'トートバッグ ポーチ付き', '春の季節にぴったりのトートバッグです。インナーポーチまたは単体でも使用可能なポーチ付。', 24800, 'B000000003', 2, 3, false, CURRENT_TIMESTAMP),
    (8, 'ショルダーバッグ', 'さらりと気軽に纏える、キュートなミニサイズショルダー。', 2800, 'B000000004', 2, 1, false, CURRENT_TIMESTAMP),
    (9, 'レザー チェーンショルダーバッグ', 'エレガントな雰囲気を放つキルティングデザインです。', 258000, 'B000000005', 2, 1, false, CURRENT_TIMESTAMP),
    (10, 'ランニングシューズ - ブルー', '柔らかいソールは快適な履き心地で、ランニングに最適です。', 12800, 'S000000001', 3, 2, false, CURRENT_TIMESTAMP),
    (11, 'メダリオン ストレートチップ ドレスシューズ', 'イタリアの職人が丁寧に手作業で作り上げた一品です。', 23800, 'S000000002', 3, 1, false, CURRENT_TIMESTAMP);
ALTER TABLE catalog_items ALTER COLUMN id RESTART WITH 12;

INSERT INTO catalog_item_assets (id, asset_code, catalog_item_id) 
VALUES 
    (1, '45c22ba3da064391baac91341067ffe9', 1),
    (2, '4aed07c4ed5d45a5b97f11acedfbb601', 2),
    (3, '082b37439ecc44919626ba00fc60ee85', 3),
    (4, 'f5f89954281747fa878129c29e1e0f83', 4),
    (5, 'a8291ef2e8e14869a7048e272915f33c', 5),
    (6, '66237018c769478a90037bd877f5fba1', 6),
    (7, 'd136d4c81b86478990984dcafbf08244', 7),
    (8, '47183f32f6584d7fb661f9216e11318b', 8),
    (9, 'cf151206efd344e1b86854f4aa49fdef', 9),
    (10, 'ab2e78eb7fe3408aadbf1e17a9945a8c', 10),
    (11, '0e557e96bc054f10bc91c27405a83e85', 11);
ALTER TABLE catalog_item_assets ALTER COLUMN id RESTART WITH 12;

MyBatis Generator 実行用のテーブル作成について

サンプルアプリケーションの実行中は、 schema.sql と data.sql が自動的に読み込まれた H2 Database がインメモリで起動します。 そのため、サンプルアプリケーションの実行用のデータベース作成の必要はありませんが、アプリケーションの停止と共にテーブルは削除されます。

よって、 MyBatis Generator を利用する際には、自動生成用のテーブルを別途用意しておく必要があります。 H2 Console を利用してデータベースを起動する場合は、以下の手順を実施します。

  1. H2 Console をインストールする。
  2. Windows 内を検索し、 H2 Console を起動する。
  3. JDBC URL に任意のパスを入力し、接続ボタンをクリックする。接続すると自動でデータベースが作成され、起動する。

    H2 Console のページ

  4. 上記の方法でエラーが発生する場合は、 H2 Console のインジケーターを右クリックし Create new database ... を選択する。

    H2 Console のインジケーター表示

  5. 任意のパス、ユーザー名、パスワードでデータベースを作成する。

    H2 データベースの作成画面

  6. 2 の手順と同様に先ほどのパス、ユーザー名、パスワードを入力して接続し、データベースを起動する。

MyBatis Generator の設定ファイルの作成⚓︎

infrastructure プロジェクトの src/main/resource フォルダーに設定ファイルである mybatisGeneratorConfig.xml を追加します。 mybatisGeneratorConfig.xml に設定する各要素については、こちら を参照してください。

サンプルアプリケーションにおける設定例は以下の通りです。

サンプルアプリケーションの mybatisGeneratorConfig.xml
mybatisGeneratorConfig.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<?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="local"  targetRuntime="MyBatis3">
        <!-- 自動生成MapperにはMapperアノテーションを付与する -->
        <plugin type="org.mybatis.generator.plugins.MapperAnnotationPlugin"/>
        <!-- 自動生成される各要素のコメントに生成時刻が出力されないように設定する -->
        <commentGenerator>
            <property name="suppressDate" value="true" />
        </commentGenerator>
        <!-- 接続先DB情報 -->
        <jdbcConnection driverClass="org.h2.Driver"
                        connectionURL="jdbc:h2:file:~/stapler;DATABASE_TO_LOWER=TRUE;DEFAULT_NULL_ORDERING=HIGH;"
                        userId=""
                        password="" />
        <!-- Model(Entity)作成先 -->
        <javaModelGenerator targetPackage="com.dressca.infrastructure.repository.mybatis.generated.entity"
                        targetProject="/dev/repos/AlesInfiny/maia/samples/web-csr/dressca-backend/infrastructure/src/main/java" />
        <!-- Mapper.xml作成先 -->
        <sqlMapGenerator targetPackage="com.dressca.infrastructure.repository.mybatis.generated.mapper"
                        targetProject="/dev/repos/AlesInfiny/maia/samples/web-csr/dressca-backend/infrastructure/src/main/resources" />
        <!-- Mapper.java作成先 -->
        <javaClientGenerator targetPackage="com.dressca.infrastructure.repository.mybatis.generated.mapper"
                        targetProject="/dev/repos/AlesInfiny/maia/samples/web-csr/dressca-backend/infrastructure/src/main/java"
                        type="XMLMAPPER" />
        <!-- 生成対象テーブル -->
        <table schema="" tableName="assets" domainObjectName="AssetEntity" mapperName="AssetMapper">
            <property name="mapUnderscoreToCamelCase" value="true" />
            <generatedKey column="id" sqlStatement="JDBC" identity="true" />
            <!-- <property name="dynamicSqlSupportClassName" value="AssetDynamicSqlSupport" />
            <property name="dynamicSqlTableObjectName" value="assets" /> -->
        </table>
        <table schema="" tableName="baskets" domainObjectName="BasketEntity" mapperName="BasketMapper">
            <property name="mapUnderscoreToCamelCase" value="true" />
            <generatedKey column="id" sqlStatement="JDBC" identity="true" />
            <!-- <property name="dynamicSqlSupportClassName" value="BasketDynamicSqlSupport" />
            <property name="dynamicSqlTableObjectName" value="baskets" /> -->
        </table>
        <table schema="" tableName="catalog_brands" domainObjectName="CatalogBrandEntity" mapperName="CatalogBrandMapper">
            <property name="mapUnderscoreToCamelCase" value="true" />
            <generatedKey column="id" sqlStatement="JDBC" identity="true" />
            <!-- <property name="dynamicSqlSupportClassName" value="CatalogBrandDynamicSqlSupport" />
            <property name="dynamicSqlTableObjectName" value="catalogBrands" /> -->
        </table>
        <table schema="" tableName="catalog_categories" domainObjectName="CatalogCategoryEntity" mapperName="CatalogCategoryMapper">
            <property name="mapUnderscoreToCamelCase" value="true" />
            <generatedKey column="id" sqlStatement="JDBC" identity="true" />
            <!-- <property name="dynamicSqlSupportClassName" value="CatalogCategoryDynamicSqlSupport" />
            <property name="dynamicSqlTableObjectName" value="catalogCategories" /> -->
        </table>
        <table schema="" tableName="orders" domainObjectName="OrderEntity" mapperName="OrderMapper">
            <property name="mapUnderscoreToCamelCase" value="true" />
            <generatedKey column="id" sqlStatement="JDBC" identity="true" />
            <!-- <property name="dynamicSqlSupportClassName" value="OrderDynamicSqlSupport" />
            <property name="dynamicSqlTableObjectName" value="orders" /> -->
        </table>
        <table schema="" tableName="basket_items" domainObjectName="BasketItemEntity" mapperName="BasketItemMapper">
            <property name="mapUnderscoreToCamelCase" value="true" />
            <generatedKey column="id" sqlStatement="JDBC" identity="true" />
            <!-- <property name="dynamicSqlSupportClassName" value="BasketItemDynamicSqlSupport" />
            <property name="dynamicSqlTableObjectName" value="basketItems" /> -->
        </table>
        <table schema="" tableName="catalog_items" domainObjectName="CatalogItemEntity" mapperName="CatalogItemMapper">
            <property name="mapUnderscoreToCamelCase" value="true" />
            <generatedKey column="id" sqlStatement="JDBC" identity="true" />
            <!-- <property name="dynamicSqlSupportClassName" value="CatalogItemDynamicSqlSupport" />
            <property name="dynamicSqlTableObjectName" value="catalogItems" /> -->
        </table>
        <table schema="" tableName="order_items" domainObjectName="OrderItemEntity" mapperName="OrderItemMapper">
            <property name="mapUnderscoreToCamelCase" value="true" />
            <generatedKey column="id" sqlStatement="JDBC" identity="true" />
            <!-- <property name="dynamicSqlSupportClassName" value="OrderItemDynamicSqlSupport" />
            <property name="dynamicSqlTableObjectName" value="orderItems" /> -->
        </table>
        <table schema="" tableName="catalog_item_assets" domainObjectName="CatalogItemAssetEntity" mapperName="CatalogItemAssetMapper">
            <property name="mapUnderscoreToCamelCase" value="true" />
            <generatedKey column="id" sqlStatement="JDBC" identity="true" />
            <!-- <property name="dynamicSqlSupportClassName" value="CatalogItemAssetDynamicSqlSupport" />
            <property name="dynamicSqlTableObjectName" value="catalogItemAssets" /> -->
        </table>
    </context>
</generatorConfiguration>

各タブの設定内容は以下の通りです。

  • <jdbcConnection>: 接続するデータベースに関する設定です。
  • <javaModelGenerator>: データベースのテーブルに対応する Java のエンティティクラスを生成するための設定です。
  • <sqlMapGenerator>: MyBatis の SQL マッピングファイルを生成するための設定です。
  • <javaClientGenerator>: MyBatis のマッパーインターフェースを生成するための設定です。
  • <table>: 生成対象となるテーブルに関する設定です。

なお、<jdbcConnection>driverClassconnectionURL は使用するデータベースに合わせて変更してください。 また、<javaModelGenerator><sqlMapGenerator> 等の targetPackagetargetProject の設定はフォルダー構成に合わせて修正してください。

次に、 <javaClientGenerator><sqlMapGenerator> で生成される XML ファイルをリソースに指定する設定を infrastructure プロジェクトの build.gradle に記述します。

build.gradle
1
2
3
4
5
6
sourceSets {
  main {
    // mybatis SQL map XML ファイルを java 以下でも検知する
    resources.srcDirs = ["src/main/java", "src/main/resources"]
  }
}

依存ライブラリの設定⚓︎

infrastructure プロジェクトの build.gradle の configurations に MyBatis Generator 実行用の依存関係のカスタム構成を定義します。

build.gradle
1
2
3
4
configurations {
  // MyBatis Generator の自動生成で利用するライブラリのための依存関係の構成を定義
  mybatisTasks
}

次に、 build.gradle の dependencies に以下のような MyBatis Generator を利用するための依存関係を追加します。

  • mybatis-generator-core:MyBatis Generator のタスクを実行するためのライブラリ

  • h2:コードの自動生成で利用する組み込みの H2 データベース

この際、依存関係は前述の configurations で定義したカスタム構成である mybatisTasks を利用します。

build.gradle
1
2
3
4
dependencies {
  mybatisTasks "org.mybatis.generator:mybatis-generator-core:x.x.x"
  mybatisTasks "com.h2database:h2:x.x.x"
}

自動生成タスクの追加⚓︎

MyBatis Generator を実行するタスク runMyBatisGenerator を定義します。 configfile には、前述 の mybatisGeneratorConfig.xml のパスを設定します。

build.gradle
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
tasks.register('runMyBatisGenerator') {
  doLast {
    // MyBatis Generator のタスクを定義します。
    ant.taskdef(
      name: 'mybatisGenerator',
      classname: 'org.mybatis.generator.ant.GeneratorAntTask',
      classpath: configurations.mybatisTasks.asPath
    )
    // MyBatis Generator による自動生成を実行します。
    ant.mybatisGenerator(
      overwrite: true,
      configfile: file('src/main/resources/mybatisGeneratorConfig.xml'),
      verbose: true
    )
  }
}

自動生成タスクの実行⚓︎

ここまでを実行した後に、適切にビルドが実行できるかを確認します。 ターミナルを用いてルートプロジェクト直下で以下を実行してください。

自動生成タスクの実行コマンド
1
./gradlew infrastructure:runMyBatisGenerator

実行後、 mybatisGeneratorConfig.xml の <javaModelGenerator><sqlMapGenerator> 等で設定した配置場所にファイルが自動生成されていることを確認してください。

ここまでの手順を実行した際の infrastructure/build.gradle の例
infrastructure/build.gradle
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
plugins {
  id 'java'
  id 'org.springframework.boot' version 'x.x.x'
  id 'io.spring.dependency-management' version 'x.x.x'
}

group = 'プロジェクトのグループ名'
version = 'x.x.x-SNAPSHOT'

java {
  toolchain {
    languageVersion = JavaLanguageVersion.of(x)
  }
}

sourceSets {
  main {
    // mybatis SQL map XML ファイルを java 以下でも検知する
    resources.srcDirs = ["src/main/java", "src/main/resources"]
  }
}

repositories {
  mavenCentral()
}

configurations {
  mybatisTasks
  all {
    exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
  }
}

dependencies {
  implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:x.x.x'
  implementation 'com.h2database:h2:x.x.x'
  implementation project(':application-core')
  implementation project(':system-common')

  mybatisTasks "org.mybatis.generator:mybatis-generator-core:x.x.x"
  mybatisTasks "com.h2database:h2:x.x.x"
  // その他、プロジェクトに必要な依存ライブラリは任意で追加してください。
}

bootJar {
  enabled = false
}

jar {
  enabled = true
}

tasks.register('runMyBatisGenerator') {
  doLast {
    // MyBatis Generator のタスクを定義します。
    ant.taskdef(
      name: 'mybatisGenerator',
      classname: 'org.mybatis.generator.ant.GeneratorAntTask',
      classpath: configurations.mybatisTasks.asPath
    )
    // MyBatis Generator による自動生成を実行します。
    ant.mybatisGenerator(
      overwrite: true,
      configfile: file('src/main/resources/mybatisGeneratorConfig.xml'),
      verbose: true
    )
  }
}