Why JOOQ?
MyBatisの方が手堅い気がしますが、JOOQを選んだ理由としては、以下のものです。
- タイプセーフ
- Annotation Processingではなく、プラグインによるコード生成
- Spring Boot Starterでサポートされていたり、開発も活発なので、発展性がある&しばらくはなくならない気がする
本記事では、「JOOQって何?」という説明は割愛して、新規プロジェクトでも既存のプロジェクトでも利用できるようなポイントをメモしておきます。
前提条件
DBのスキーマはFlywayで管理されているものとします。ただし、JOOQとFlywayは直接関係はないので、他のマイグレーションツールでも多分やり方は同じはずです。
- Java 11
- Gradle 5.1
- Java 11に対応しているのが5.0からであるため、5.0以上が必須です。
- Spring Boot 2.1.1.RELEASE
- JOOQ: 3.11.7
- Spring Boot の依存関係管理で解決されるため、明示的に指定はしていません。
手順
build.gradle
buildscript { ext { springBootVersion = '2.1.1.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") classpath('org.glassfish.jaxb:jaxb-runtime:2.3.1') // (1) } } plugins { id 'org.flywaydb.flyway' version '5.2.4' id 'nu.studer.jooq' version '3.0.2' // (2) } apply plugin: 'java' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = 11 repositories { mavenCentral() } dependencies { // 略 implementation('org.springframework.boot:spring-boot-starter-jooq') // (3) // 略 jooqRuntime('org.glassfish.jaxb:jaxb-runtime') // (1) jooqRuntime('javax.activation:javax.activation-api') // (1) } flyway { url = 'jdbc:mysql://127.0.0.1:3306/testdb' user = 'dbuser' password = 'dbpass' } jooq { // (4) main(sourceSets.main) { jdbc { url = 'jdbc:mysql://127.0.0.1:3306/testdb' user = 'dbuser' password = 'dbpass' } generator { name = 'org.jooq.codegen.DefaultGenerator' database { name = 'org.jooq.meta.mysql.MySQLDatabase' includes = '.*' excludes = 'flyway_schema_history' // (5) inputSchema = 'testdb' } strategy { name = 'org.jooq.codegen.DefaultGeneratorStrategy' } generate { } target { // (6) packageName = 'com.example.demo.jooq' directory = 'src/main/java' } } } } project.tasks.getByName('compileJava').dependsOn -= 'generateMainJooqSchemaSource' // (7)
説明 | |
---|---|
(1) | Java 11からはJAXBが外されてしまうため、必要な依存関係を明示的に追加します。 |
(2) | Gradleプラグインとしてgradle-jooq-pluginを適用します。 JOOQのコード生成を行う方法はいくつかありますが、Gradleタスクとして実行できると簡単かつ便利なので、これを使います。 |
(3) | アプリケーションからJOOQを使うための依存を追加。 |
(4) | JOOQコード生成のための設定を記述します。jooq-codegenのXMLでの設定の替わりになるものです。 |
(5) | Flywayがスキーマ管理を行うために作成するテーブルは、アプリケーションから使うことはないので、コード生成から除外します。 |
(6) | 自動生成されるコードの出力先です。 |
(7) | デフォルトでは、compileJavaタスクが実行される前にコード生成も実行されるのですが、これを除外します。 こちらは有効化するかどうかはお好みで。 |
タスク実行
$ ./gradlew generateMainJooqSchemaSource
開発の進め方
上記の1.と2.で一つのfeature(プルリクエスト)になっているのが分かりやすく、トラブルが起きにくい気がします。
また、自動生成されたコードは、直接編集しないよう、開発チームで徹底しておく必要がありそうです。手動で変更してしまうと次にコード生成された時に上書きされてしまうので。
(追記)自動生成されたコードをコミットするべきか?
並行開発の妨げになるので「自動生成されたコードはコミット対象外!」という主張もあり、なるほどと思いました。
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
プロジェクトの規模が大きく、スキーマ変更が頻繁に発生する場合は、提言されているとおり、コミット対象外とした方がよいのかもしれません。