🦁

jOOQでMySQLのTINYINT(1)をBooleanにマップする方法

2022/03/18に公開

jOOQでMySQLのBooleanをジェネレートしたところ、型がBooleanにマッピングされていないことが発覚。
調べてみると、この問題の解決方法をjOOQの公式がブログにしてくれていました。(ただし、Java + Mavenのサンプルのみ)

https://blog.jooq.org/how-to-map-mysqls-tinyint1-to-boolean-in-jooq/

この記事では、この問題の簡単な解説と公式のJava + Mavenの実装例を参考に、Kotlin + Gradleで実装し直したものを紹介します。

原因

原因は、MySQLの仕様でBooleanがTINYINT(1)として表現されていることでした。
その結果、TINYINT(1)をjOOQは正しく認識して型に変換するため、Booleanにならないことが問題でした。

また公式としてはTINYINT(1)を使用するユーザーがいる可能性を考慮して、デフォルトでTINYINT(1)をBooleanに変換する気はないようです。

そのため、自分でジェネレートの設定を上書きする必要があるという訳です。

解決策

実際の解決策としては、configurationsのForced typesで型変換の上書きします。
以下が今回のBooleanを上書きするための設定です。

build.gradle.kts
jooq {
    configurations {
        create("main") {
            jooqConfiguration.apply {
                ... // 省略
                generator.apply {
                    name = "org.jooq.codegen.KotlinGenerator"
                    database.apply {
                        ... // 省略
                        forcedTypes.addAll(
                            listOf(
                                ForcedType().apply {
                                    name = "boolean"
                                    includeTypes = "(?i:TINYINT\\(1\\))"
                                }
                            )
                        )
                    }
                   ... // 省略
                }
            }
        }
    }
}

nameにはjooqGenerateしたい型、includeTypesには実際にDBに存在する型を指定しておくことで型が上書きされます。
(今回のincludeTypesにはJavaの正規表現を利用しています)

複数定義する場合はlistにForcedTypeを追加していけば良いです。

感想

Booleanは基本的な型だと思っていたので、最初は「なんでぇ?」となりましたが、意外と重要なことだったので誰かのお役に立てれば幸いです。

あと最近、MySQLからMariaDBに乗り換える機会があったのですが、MariaDBでも同様にTINYINT(1)でBooleanが表現されていたので、この実装が地味に役立っています!

参考

Discussion