TL;DR
-
jOOQ
はReactor
に依存しないため、jOOQ
内の処理からはReactor
固有の機能(Reactive Context
1)にアクセスできない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
現在の話です。 ↩