Squerylを使用してトランザクション分離レベルを設定するにはどうすればよいですか?
たとえば、現在私はPostgresqlを使用しており、特定の単一トランザクションに対してシリアル化可能な分離が必要です。私はLiftWebフレームワークでプレーンなSquerylとSqueryl-Recordの両方を使用しています。
もちろん、他のデータベースでは(単一のトランザクションではなく)セッション全体で他の分離レベルが必要になる場合があるため、一般的な回答が望ましいです。
アップデート:
私はDaveWhittakerのコードのこの修正バージョンに行き着きました:
def transactionWith[T](isolation: Int)(block: => T): T =
transaction {
val connection = Session.currentSession.connection
connection.rollback // isolation cannot be changed in the middle of a tx
connection.setTransactionIsolation(isolation)
block
}
重要なのは、トランザクションがすでに開始されている場合、分離レベルを変更することはできないということです。これは私の場合であり、ロールバックがなければ、次のようになります。
org.postgresql.util.PSQLException:トランザクションの途中でトランザクション分離レベルを変更できません。
inTransaction {}ではなくtransaction{}を使用している限り、すぐにロールバックを実行しても害はないと思います。
分離レベルは、transaction {}がコミットまたはロールバックした後、接続が接続プールに戻る前にリセットする必要があります。それを達成する方法がわかりません。しかし、私の場合、c3p0接続プールは分離レベルをリセットしているようで、自分でクリーンアップしなくても、すべてのトランザクション{}はデフォルトの分離レベルで開始されます。
私があまり満足していないのは、対立がある場合の例外です。特にそのような例外をキャッチして、トランザクションを再試行したいと思います。しかし、これは単なる一般的なランタイム例外です。
java.lang.RuntimeException:ステートメントの実行中に例外が発生しました:エラー:同時更新のため、アクセスをシリアル化できませんでした
残念ながら一般的な別の例外(org.postgresql.util.PSQLException)をラップします。
完璧ではありませんが、Squerylがトランザクション分離のサポートを取得するまでは機能します。上記のコードをSqueryl0.9.4で使用しています。