gpt4 book ai didi

database - 在 Squeryl 中设置事务隔离级别

转载 作者:搜寻专家 更新时间:2023-10-30 19:44:03 25 4
gpt4 key购买 nike

如何使用 Squeryl 设置事务隔离级别?

例如,现在我正在使用 Postgresql 并且需要对特定的单个事务进行可序列化隔离。我将纯 Squeryl 和 Squeryl-Record 与 Lift Web 框架一起使用。

对于整个 session (而不是单个事务),其他人当然可能需要其他数据库的其他隔离级别,因此一般的答案更可取。

更新:

我最终得到了 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.

只要我使用的是事务{}而不是 inTransaction{},我认为立即回滚应该没有坏处。

隔离级别应该在 transaction{} 提交或回滚之后,但在连接返回到连接池之前重置。我不确定如何做到这一点。但在我的例子中,c3p0 连接池似乎重置了隔离级别,每个事务{}都以默认隔离级别开始,即使我从未亲自清理过它们也是如此。

我不太满意的是发生冲突时的异常。我想专门捕获这样的异常并重试交易。但这只是一个通用的运行时异常:

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 一起使用。

最佳答案

现在这将是一个有点手动的过程。如果您在整个 session 中都需要它,那么我想您可以简单地在 SessionFactory 中设置适当的级别,即

SessionFactory.concreteFactory = Some(()=> {
val connection = java.sql.DriverManager.getConnection("...")
connection.setTransactionIsolation(...)
Session.create(connection, new PostgreSqlAdapter)
})

对于单笔交易来说,难度会大一些。您可以使用 Session.currentSession 或 Session.currentSessionOption 访问当前 session ,您必须在事务发生之前设置隔离级别,然后再将其设置回来。当然,创建您自己的函数并不会太难:

def transactionWith(isolation: Int)(block: => T): T = {
trasaction{
val connection = Session.currentSession.connection
val oldIsolation = connection.getTransactionIsolation()
connection.setTransactionIsolation(isolation)
try {
block
} finally {
connection.setTransactionIsolation(oldIsolation)
}
}
}

然后你会像这样使用它

transactionWith(Connection.TRANSACTION_SERIALIZABLE){
from(blablabla)(......)
}

我认为这行得通,但是 a) 我不完全确定何时应该设置隔离级别,我假设在执行任何其他语句之前在当前事务中设置它会行得通,并且 b) 我还没有' 试图编译以上内容,因此可能存在语法错误。不管怎样,我想它会给你一个大概的想法。

关于database - 在 Squeryl 中设置事务隔离级别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8272848/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com