わくわく技術ブログ

プログラミング・統計・機械学習

JavaのDBアクセスライブラリ jOOQ の紹介

先日、とある会社の方に、DBアクセスするにはjOOQ(ジョーク 【訂正】ジュークと読むらしく公式に発音記号が定義されている)というライブラリが良いと教えて頂いた。 名前はなんとなく見たことがある気がするものの、実際のところどういった物なのか知らなかったので、個人的に気になる点を調べてみた。

実際に使い倒したわけではなく、使ってみたら不満とか解決策とか見つかるかもしれないので、その点はご容赦を。

対象読者

  • JPA(Hibernate)/MyBatis/Doma2 など他のDBアクセスライブラリの利用経験がある人
  • jOOQのことを知りたい人、検討材料を探している人

jOOQが何か簡単に言うと?

ドキュメントを探しても、ズバリ一言で「jOOQは〇〇である」という記載は見つからない。ドキュメント 3.3. Different use cases for jOOQ

jOOQ has originally been created as a library for complete abstraction of JDBC and all database interaction.

と書かれており、DBアクセスを全てカバーしたいことは分かるが、どういう特徴があるかは一言では書かれていない。

一方で、他のツールとの対比や利用のバリエーションは色々書かれている。

例えば、jOOQのGitHubリポジトリREADME.mdを私なりに要約すると、JPALINQのような仕組みはSQLを隠そうとするあまり高度なクエリ発行が難しいと言っている。

また、ドキュメント 3.3. Different use cases for jOOQから抜粋すると、

  • 型安全にSQLを組み立てられる。
  • クエリ実行に便利な機能を用意している。ロギングなどの開発補助も入っている。
  • HibernateとjOOQを組み合わせて使うのもあり。
  • jOOQにはソースコードジェネレーターがあるけど、それは使わなくてもよい。

などあれこれ書かれている。

これらを踏まえると、「Javaの型の恩恵を受けながらSQLを直接記述したいときに使うライブラリ」と言えそうだ。

競合は?

jOOQ公式ではJPA(Hibernate)を非常に意識している。ただ実際にはSQLを自在に実行できるライブラリとして、MyBatisDoma 2などが競合にあたるように思う。

MyBatisもDoma 2もいくつか使い方があるが、主には、

  • MyBatis … SQLをファイルに記述する。条件分岐などはXMLタグで表現する。
  • Doma 2 … SQLをファイルに記述する。SQLコメントをDoma 2が解析して条件分岐などを制御する。
  • jOOQ … JavaソースコードSQLを記述する。

という使い方になると思われる。型安全にするためにJavaの中でSQLを組み立てるのにこだわっている点で、他のライブラリとは方向性が異なる。

気になったこと一覧

分類 実現したいこと 調査結果 URL コメント
参照系 JOIN句 https://www.jooq.org/doc/3.16/manual/sql-building/table-expressions/joined-tables/
参照系 サブクエリ(相関サブクエリ) https://www.jooq.org/doc/3.16/manual/sql-building/column-expressions/scalar-subqueries/
参照系 ロック取得 https://www.jooq.org/doc/3.16/manual/sql-building/sql-statements/select-statement/for-update-clause/
参照系 カーソル取得(大量レコードの順次取得) https://www.jooq.org/doc/3.16/manual/sql-execution/fetching/lazy-fetching/
参照系 HINT指定 https://www.jooq.org/doc/3.16/manual/sql-building/sql-statements/select-statement/oracle-hints/ Oracleと同じコメント形式の場合対応可、型安全ではない
更新系 batchExecute https://www.jooq.org/doc/3.16/manual/sql-execution/batch-execution/
共通 プリペアードステートメントの再利用 https://www.jooq.org/doc/3.16/manual/sql-execution/reusing-statements/
共通 動的なSQLの組み立て https://www.jooq.org/doc/3.16/manual/sql-building/dynamic-sql/ 簡潔さよりシンプルさ重視か
共通 プリペアードステートメントの利用(SQLインジェクション対策) https://www.jooq.org/doc/3.16/manual/sql-execution/statement-type/
共通 組み込み関数呼び出し, キャストなど 〇? https://www.jooq.org/doc/3.16/manual/sql-building/column-expressions/ よく使う関数は揃っていそうだが、足りないものもきっとある
共通 エラー処理 https://www.jooq.org/doc/3.16/manual/sql-execution/exception-handling/ jOOQ独自例外を持っているが、Spring Bootを利用する場合はSpringの例外に変換される。
※型名が同じDataAccessExceptionなので要注意。
共通 Spring Bootとの連携
1.Starter/AutoConfiguration
https://github.com/spring-projects/spring-boot/blob/v2.6.4/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jooq/JooqAutoConfiguration.java
共通 Spring Bootとの連携
2.例外変換
https://docs.spring.io/spring-boot/docs/2.6.4/api/org/springframework/boot/autoconfigure/jooq/JooqExceptionTranslator.html
共通 Spring Bootとの連携
3.コード生成
https://www.jooq.org/doc/3.16/manual-single-page/#codegen-generate-annotations Springのアノテーションを付与する設定などもあり
共通 Spring Bootとの連携
4.テスト補助
https://docs.spring.io/spring-boot/docs/2.6.4/reference/html/features.html#features.testing.spring-boot-applications.autoconfigured-jooq
共通 生成されるSQL文の出力 https://www.jooq.org/doc/3.16/manual/sql-execution/logging/ ExecuteListenerを実装することでカスタマイズ可能
※SpringBootのAutoConfigurationで設定されるExecuteListenerが@Order(0) であることに注意する
共通 テスト補助 https://www.jooq.org/doc/latest/manual/sql-execution/mocking-connection/ データ読み込みとかも可

感想

気になる事を一覧で出してみた結果、ほとんどが「○」だったので実用性は十分だと思う。

悩む点:ベストマッチなシチュエーション

SQLライクな記述をしたいという需要に応えるライブラリなので、複雑なSQL、特にSELECT文を発行するときに真価を発揮するはずだと思ったので少し考えてみた。

複雑なSQLには、

  1. 発行するSQLが複雑
  2. SQLの組み立てが複雑

の2パターンがあると思う。

1.については、頭の中でSQLを考えるのであれば、Javaではなく別ファイルにSQLを書く形式の方が素直なのではと思う。 一方で2.については、Javaの処理で書くよりも、MyBatisでXMLで宣言的に書いたりする方がスッキリすると個人的には感じていて、これもjOOQがベストとは言いかねる感じがある。

ではどんな時に真価を発揮するのか?
これは想像になってしまうが、そこまで複雑ではないけど、色々なパターンのSQLを書かなくてはいけないときなのかなと今のところ思っている。

あと、自分は普段Javaを書いているが、Kotlinなどから呼び出すときには印象が変わるかもしれない。

他より分かりやすく優れる点

Spring Boot連携の扱いは特徴である。

StarterパッケージがSpring Bootから公式に出されているのは頼もしいポイントで、MyBatisやDoma2よりもSpringのバージョンアップで使えなくなるリスクが低いと考えて良いと思う。 (Spring Bootが出している情報全般に言えることだが)ドキュメントが少ないのでソースコードを読む必要があるのが玉に瑕だが、それでも十分な利点だと思う。

あとは、上には表現されていない使い方の特徴として、基本的にソースコードはDB定義から自動生成するのが基本のようになっている点がある。 逆に、自動生成しないと文字列で記述する部分が多くて、型安全の恩恵を受けることが出来なくなってしまうとも言える。

自動生成にもオプションが多数あり、最初にどういうコードを自動生成させるかが大事になってくる点が他との違いである。

最後に

この手のライブラリを使うときに何を重視するかは人それぞれだと思う。上記を見て気になったことがあれば試して見て欲しい。
自分ももう少し触ってみて、気づいた事があれば更新を掛けていきたい。