spring boot ・ doma を使用した際の eclipse (gradle) の環境設定

spring boot で作成した プログラムで、データベースにアクセスする際の O/Rマッパーに doma を選択した際に、依存管理ツールに doma-spring-boot-stater を指定します。

いざ、eclipse で開発しようとした際、doma-n.n.n.jar を使用した環境設定は、公式(※1)を含めて多数存在します。しかし、doma-spring-boot-stater に関しての詳細な設定方法等が見つからなかったので、調査した内容をここに記載します。

■使用環境

windows 10

eclipse 4.15.0
gradle 6.3

doma-spring-boot-starter 1.4.0
doma-processor 2.35.0

■ファクトリーパスの設定

公式ページの説明では、Maven Central Repository より doma を入手し、ファクトリーパスに doma-n.n.n.jar を設定するように記載されています。(※1)

doma-spring-boot-stater の場合、gradle に記載する依存の設定は以下の通りになります。
※必要な箇所のみ抜粋

dependencies {
  implementation "org.seasar.doma.boot:doma-spring-boot-starter:1.4.0"
  annotationProcessor "org.seasar.doma:doma-processor:2.35.0"
}

上記を反映すると、doma-n.n.n.jar が取り込まれません。
代わりに、doma-core-2.35.0.jar が取り込まれます。

gradle の dependencies に設定した doma-processor と共に、doma-core-2.35.0.jar をファクトリーパスに設定する必要があります。
この時、下記画像の通りの順番も関係ありますので、ご注意ください。

※例)[外部jarの追加]より.gradle 配下のファイルを直接指定

■DOMA4019 エラー対応

gradle をデフォルトで使用した際 eclipse 上で[ DOMA4019 ]エラーが発生し、ビルドが失敗します。

javaのビルドパスで、「ソース・フォルダーごとに出力フォルダーの指定を可能にする」にチェックが入っている為です。
こちらのチェックを外すと、エラーが解消されます。

以上、eclipse での躓き箇所と 解決方法でした。

最後に、上記を含めた gradle の設定を公開します。

■gradle の設定

//  doma の gradle設定について、下記を参照してください。
//      https://doma.readthedocs.io/en/2.20.0/build/(日本語訳ページ)

// テンポラリディレクトリのパスを定義する
ext.domaResourcesDir = "${buildDir}/tmp/doma-resources"

  // ---- debug用 -------------------------------------
  //  println "processResources.destinationDir is ${processResources.destinationDir}"
  //  println "ext.domaResourcesDir            is ${ext.domaResourcesDir}"
  //  println "compileJava.destinationDir      is ${compileJava.destinationDir}"

// domaが注釈処理で参照するリソースをテンポラリディレクトリに抽出
task extractDomaResources(type: Copy, dependsOn: processResources)  {
  from processResources.destinationDir
  include 'doma.compile.config'
  include 'META-INF/**/*.sql'
  include 'META-INF/**/*.script'
  into domaResourcesDir
}

// テンポラリディレクトリ内のリソースをcompileJavaタスクの出力先ディレクトリにコピーする
task copyDomaResources(type: Copy, dependsOn: extractDomaResources)  {
  from domaResourcesDir
  into compileJava.destinationDir
}

compileJava {
  // 上述のタスクに依存させる
  dependsOn copyDomaResources
  // テンポラリディレクトリをcompileJavaタスクの入力ディレクトリに設定する
  inputs.dir domaResourcesDir
  options.encoding = 'UTF-8'
}

repositories {
  mavenCentral()
  mavenLocal()
  maven {url 'https://oss.sonatype.org/content/repositories/snapshots/'}
}

dependencies {
  implementation "org.seasar.doma.boot:doma-spring-boot-starter:1.4.0"
  annotationProcessor "org.seasar.doma:doma-processor:2.35.0"
}

eclipse {
  classpath {
    // [DOMA4019] 対応
    //   ソース毎の出力先指定を解除
    file.whenMerged {
      entries.each { entry ->
        if (entry.kind == 'src' && entry.hasProperty('output')) {
          entry.output = null
        }
      }
    }
  }
}

eclipse.jdt.file {
    // [Javaコンパイラー]->[注釈処理] の設定
    def  eclipseAptPrefsFile = '.settings/org.eclipse.jdt.apt.core.prefs'
    file(eclipseAptPrefsFile).write """\
      |eclipse.preferences.version=1
      |org.eclipse.jdt.apt.aptEnabled=true
      |org.eclipse.jdt.apt.genSrcDir=.apt_generated
      |org.eclipse.jdt.apt.genTestSrcDir=.apt_generated_tests
      |org.eclipse.jdt.apt.reconcileEnabled=true
      |""".stripMargin()


    // [Javaコンパイラー]->[注釈処理]->[ファクトリーパス] の設定
    def f = file(".factorypath")
    def w = new FileWriter(f)
    def jar = ""

    def xml = new groovy.xml.MarkupBuilder(w)
    xml.setDoubleQuotes(true)
    xml."factorypath"() {
      // doma-core.jar の読込み
      jar = configurations.annotationProcessor.find { File file -> file.name.matches('doma-core[^//]*') }
      'factorypathentry'(kind: 'EXTJAR', id: jar, enabled: true, runInBatchMode: false)

      // doma-processorjar の読込み
      jar = configurations.annotationProcessor.find { File file -> file.name.matches('doma-processor[^//]*') }
      'factorypathentry'(kind: 'EXTJAR', id: jar, enabled: true, runInBatchMode: false)
    }
    w.close()
}

上記を設定し、gradle eclipse もしくは、eclipse 上で [Gradle] -> [Gradle プロジェクトのリフレッシュ]を実行すると、本記事のファクトリーパスの設定・DOMA4019 を自動対応します。

■参考情報
※1:参考にした、doma 公式の設定ページ。
   https://doma.readthedocs.io/en/2.20.0/build/


DBの環境差異調査(mysql編)

システム開発において、
 ・本番
 ・検品(ステージング)
 ・開発
と環境が別れている事は通常よくあることであり、それにともないDBの環境もそれぞれ存在することとなります。

開発体制が小規模であったり、管理ルールが整っていない時などに、それぞれのDB環境に差異が発生している事が多々あります。
その差異を視覚化し、容易に把握するための方法をご紹介します。

※今回使用した環境
 ・mysql : 5.6.40
      https://dev.mysql.com/downloads/windows/installer/5.6.html
 ・ローカル環境:windows 10
 ・比較ツール:WinMerge 2.14.0
        https://winmerge.org/downloads/?lang=ja

1.差分抽出SQL の用意


SELECT '### COLUMN情報 #########################' AS '';
SELECT TABLE_NAME
     , COLUMN_NAME
--   , ORDINAL_POSITION
     , COLUMN_TYPE
     , COLUMN_DEFAULT
     , IS_NULLABLE
     , COLUMN_KEY
     , IFNULL( COLLATION_NAME , '')      COLLATION_NAME
     , IFNULL( CHARACTER_SET_NAME , '')  CHARACTER_SET_NAME
     , COLUMN_COMMENT 
  FROM INFORMATION_SCHEMA.COLUMNS
 WHERE TABLE_SCHEMA = @DB_DATABASE
 ORDER BY TABLE_NAME , COLUMN_NAME
;

SELECT '### INDEX情報 ##########################' AS '';
SELECT TABLE_NAME
     , INDEX_NAME
     , SEQ_IN_INDEX
     , COLUMN_NAME
  FROM INFORMATION_SCHEMA.STATISTICS
 WHERE TABLE_SCHEMA = @DB_DATABASE
 ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX 
;

mysql では、DBの情報を INFORMATION_SCHEMA 内に保持しており、その情報を出力しています。
※上記例では、カラムの順番を考慮せず、カラム名順で評価しています。

2.差分抽出SQL の実行

上記 SQL をファイルに保存して、コマンドで実行します。
※ここでは、「db-columns.sql」と命名します。

mysql -e "set @DB_DATABASE='DB名'; source db-columns.sql ;" > 環境.txt

※接続情報等は、省略させて頂いています。

こちらの実行した結果は以下の通りとなります。
※ mysql のバージョンに関わらず、全てのバージョンで稼働すると思います。


### COLUMN情報 #########################
TABLE_NAME	COLUMN_NAME	COLUMN_TYPE	COLUMN_DEFAULT	IS_NULLABLE	COLUMN_KEY	COLLATION_NAME	CHARACTER_SET_NAME	COLUMN_COMMENT
hoge	birthday	date	NULL	YES				
hoge	key	int(11)	NULL	NO	PRI			
hoge	name	varchar(50)	NULL	YES	MUL	utf8_general_ci	utf8	
hoge	sex	char(1)	0	YES		utf8_general_ci	utf8	

### INDEX情報 ##########################
TABLE_NAME	INDEX_NAME	SEQ_IN_INDEX	COLUMN_NAME
hoge	hoge_i1	1	name
hoge	hoge_i1	2	birthday
hoge	PRIMARY	1	key

3.SQL実行結果の比較

上記、環境毎に出力し、その結果を winmerge 等で比較する事が出来ます。
例えば、ローカルの環境と比較。

別のタブで画像を開くと、大きな画像で参照できます。

上記は、以下の テーブルを比較した結果なのですが、

-- 左のDDL
CREATE TABLE `hoge` (
	`key` INT(11) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(50) NULL DEFAULT NULL,
	`sex` CHAR(1) NULL DEFAULT '0',
	`birthday` DATE NULL DEFAULT NULL,
	PRIMARY KEY (`key`),
	INDEX `hoge_i1` (`name`, `birthday`)
)

-- 右のDDL
CREATE TABLE `hoge` (
	`key` INT(11) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(50) NULL DEFAULT NULL,
	`sex` VARCHAR(1) NULL DEFAULT '0',
	`birthday` TIMESTAMP NULL DEFAULT NULL,
	PRIMARY KEY (`key`),
	INDEX `hoge_i1` (`name`)
)

WinMarge 上で、差分行が色分けされているのが判るかと思います。
・DATE型 と TIMESTAMP 型 の差異
・CHAR型 と VARCHAR型 の差異
・INDEX の差異

※Oracle ですと、「USER_TAB_COLUMNS」・「USER_IND_COLUMNS」テーブルを使用すると、同じ情報が取得できます。

author k.tomita