Как установить уровень изоляции транзакции с помощью Squeryl?
Например, сейчас я использую Postgresql и мне нужна сериализуемая изоляция для отдельных транзакций. Я использую как простой Squeryl, так и Squeryl-Record с веб-фреймворком Lift.
Другим, разумеется, могут понадобиться другие уровни изоляции для других баз данных для целых сеансов (а не отдельных транзакций), поэтому предпочтительны общие ответы.
Обновление:
Я закончил с этой модифицированной версией кода Дэйва Уиттекера:
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 {}, я думаю, что немедленный откат не принесет вреда.
Уровень изоляции должен быть сброшен после фиксации или отката транзакции {}, но до возврата соединения в пул соединений. Я не уверен, как это сделать. Но в моем случае пул соединений c3p0, по-видимому, сбрасывает уровень изоляции, и каждая транзакция {} начинается с уровня изоляции по умолчанию, даже если я сам никогда их не очищаю.
Что меня не устраивает, так это исключение, когда возникает конфликт. Я хотел бы специально отловить такое исключение и повторить транзакцию. Но это всего лишь общее исключение времени выполнения:
java.lang.RuntimeException: исключительная ситуация при выполнении оператора: ОШИБКА: не удалось сериализовать доступ из-за одновременного обновления
Оборачивает еще одно исключение, которое, к сожалению, также является общим (org.postgresql.util.PSQLException).
Не идеально, но работает, пока Squeryl, надеюсь, не получит поддержку для изоляции транзакций. Я использую приведенный выше код с Squeryl 0.9.4.