如何使用Squeryl设置事务隔离级别?
例如,我现在正在使用Postgresql,并需要针对特定的单个事务使用可串行化隔离。我同时使用纯Squeryl和带有Lift Web框架的Squeryl-Record。
当然,其他人可能需要为其他数据库设置不同的隔离级别,而不是针对单个事务,而是整个会话,因此通用答案更可取。
更新:
最终,我采用了Dave Whittaker代码的修改版本。
事情是这样的,如果事务已经开始,您就无法更改隔离级别。 对于我来说,没有回滚,我会收到以下错误信息:
org.postgresql.util.PSQLException: Cannot change transaction isolation level in the middle of a transaction.
只要我使用transaction{}而不是inTransaction{},立即回滚应该不会有害。
隔离级别应在transaction{}提交或回滚之后但在连接返回到连接池之前重置。 我不确定如何完成这一点。 但在我的情况下,c3p0连接池似乎会重置隔离级别,并且每个transaction{}都以默认隔离级别启动,即使我从未自己清理过它们。
我不太满意的是当发生冲突时的异常。 我想特别捕获这样的异常并重试事务。 但它只是一个通用的运行时异常:
java.lang.RuntimeException: Exception while executing statement : ERROR: could not serialize access due to concurrent update 它包装了另一个不幸也很通用的异常(org.postgresql.util.PSQLException)。
虽然不完美,但它可以胜任,直到Squeryl希望得到事务隔离支持。 我正在使用上面的代码与Squeryl 0.9.4。
例如,我现在正在使用Postgresql,并需要针对特定的单个事务使用可串行化隔离。我同时使用纯Squeryl和带有Lift Web框架的Squeryl-Record。
当然,其他人可能需要为其他数据库设置不同的隔离级别,而不是针对单个事务,而是整个会话,因此通用答案更可取。
更新:
最终,我采用了Dave Whittaker代码的修改版本。
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: Cannot change transaction isolation level in the middle of a transaction.
只要我使用transaction{}而不是inTransaction{},立即回滚应该不会有害。
隔离级别应在transaction{}提交或回滚之后但在连接返回到连接池之前重置。 我不确定如何完成这一点。 但在我的情况下,c3p0连接池似乎会重置隔离级别,并且每个transaction{}都以默认隔离级别启动,即使我从未自己清理过它们。
我不太满意的是当发生冲突时的异常。 我想特别捕获这样的异常并重试事务。 但它只是一个通用的运行时异常:
java.lang.RuntimeException: Exception while executing statement : ERROR: could not serialize access due to concurrent update 它包装了另一个不幸也很通用的异常(org.postgresql.util.PSQLException)。
虽然不完美,但它可以胜任,直到Squeryl希望得到事务隔离支持。 我正在使用上面的代码与Squeryl 0.9.4。