追記
この問題は3.20(追記時点では未リリース)で改善されるそうです。
ただし、Kotlin Coroutinesと併用する場合には、特定の書き方をしなければ問題が起きるそうです。
TL;DR
-
jOOQはReactorに依存しないため、jOOQ内の処理からはReactor固有の機能(Reactive Context1)にアクセスできない2- これによって期待したような結果が得られない場合が有る
- この問題を回避するには都度
Connectionを取得してDSLContextを発行する形が有効
ConnectionFactoryからDSLContextを初期化する際に起きる問題
jOOQの公式ブログでは、R2DBCを利用する際のサンプルコードとしてConnectionFactoryからDSLContextを初期化する例が紹介されています。
記事に掲載されているサンプルコードConnectionFactory connectionFactory = ConnectionFactories.get( ConnectionFactoryOptions .parse("r2dbc:h2:file://localhost/~/r2dbc-test") .mutate() .option(ConnectionFactoryOptions.USER, "sa") .option(ConnectionFactoryOptions.PASSWORD, "") .build() ); DSLContext ctx = DSL.using(connectionFactory);
一方、この形で初期化したDSLContextをSpring WebFluxで利用すると、Springが提供するReactiveTransactionManagerによるトランザクションが効かなかったり、R2DBC PoolによるLifecycleサポート内からReactive Contextにアクセスできないといった問題が発生します。
何故こうなるのか
jOOQはReactive Streamsのみに依存して実装実装する方針を採っています。
一方、ReactorはReactive Streamsを拡張して実装されたプロジェクトであり、Reactive ContextはReactor固有の機能です。
このため、jOOQを介した場合Reactive Contextは失われてしまいます。
また、ReactiveTransactionManagerもReactive Contextに依存した機能であり、jOOQの内側から利用することはできません。
この問題はjOOQの設計方針上不可避で、Reactive StreamsとReactorの両方に共通のコンテキスト機能が入りでもしない限りは解決されないものと思われます。
対策方法
それでもjOOQを使う場合、Reactive Contextが有効なスコープでConnectionを発行し、Connectionから初期化したDSLContextを使い回す方法で対策できます。
例に関しては自分の過去記事をご参照下さい。
-
この機能はドキュメント上単に
Contextと呼称されていますが、分かりやすさのためこの記事ではReactive Contextと呼称します。 ↩ -
この記事は
jOOQ 3.16.10現在の話です。 ↩