Первый вопрос. Какая связь существует между уровнем изоляции транзакций, параметрами JPA Lock.READ / Lock.WRITE
и версиями @Version
(Оптимистическая блокировка)? Я более менее понял по отдельности каждую из этих 3 разделов, но не понимаю, как они связаны между собой. Выбранный уровень изоляции транзакций дает некие «гарантии» при проведении операций с таблицами. Параметры Lock.READ/Lock.WRITE
позволяют добиться блокировки полей таблицы при проведении операций. Если я правильно понял, для этого как раз и используются поле @Version
. Но все таки не до конца улавливаю связь между эти тремя понятиями. Или они дополняют друг друга, или это разные способы решения одних и тех же проблем. В общем, буду очень благодарен за ответ или же ссылку, где можно прочесть информацию именно по вопросы связи между этими понятиями и их совместном использовании.
Второй вопрос. Каким способом в Hibernate можно указать требуемый уровень изоляции транзакции для конкретной транзакции? И принято ли так делать?
Спасибо.
Попробую ответить по порядку:
Как соотносятся Lock
и уровни изоляции
Lock
относится к доступу к данным (то есть затрагивает и чтение и запись и модификацию);Lock
обеспечивает работоспособность различных уровней изоляции данных, в самом тупом примере: если у вас стоит уровень изоляции READ_COMMITTED
, то вставка произведенная параллельной сессией будет локирована на запись пока сессия не выдаст commit()
, но лок на чтение будет открыт сразу при запросе вашего select
, а при REPEATABLE_READ
оба лока (на чтение и запись) будут стоять до commit()
- соответственно ваш select
увидит результаты модификации только после коммита.Каким способом в Hibernate можно указать требуемый уровень изоляции транзакции для конкретной транзакции?
Вообще это не сильно здорово. Уровень изоляции транзакций это принадлежность коннекта к БД, соответственно фактически изменение уровня изоляции равносильно переконнекту к БД, а насколько это дорогая операция вы сами можете оценить исходя из имеющейся у вас ситуации.
Тем не менее, если вы таки решили менять перед каждой транзакцией уровень изоляции транзакций, то самый простой способ это отправить в СУБД raw SQL query (любой ORM это поддерживает), типа:
ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE
Вопрос лёгкий, но ответ слишком длинный. Лучше книжки почитать.
Уровни изоляции, блокировки настоящие и оптимистические - работают каждый над своей проблемой. Прямо они не связаны. Подбирая их комбинацию, получаете то, что Вам нужно.
В jpa предусмотрены как оптимистичные режимы блокировки (полностью полагаются на @Version), так и пессимистичные (которые выполняются сервером базы данных):
OPTIMISTIC (он же READ)
OPTIMISTIC_FORCE_INCREMENT (он же WRITE)
PESSIMISTIC_READ
PESSIMISTIC_WRITE
PESSIMISTIC_FORCE_INCREMENT
Как изменить уровень изоляции.
Если управляете транзакцией самостоятельно, то и меняйте как хотите (сonnection.setTransactionIsolation? Нужно только connection извлечь из entity из managera). А например JTA изменить вряд ли получится. Там уровень задаётся в конфигурации datasource и изменение его не предполагается. Кажется именно так. Хотя можете уточнить этот момент. Всё течёт, всё изменяется. Может это уже не так.
Некоторую информацию по данному вопросу можно почерпнуть из статьи с хабра
UPD по второму вопросу:
Аннотация @Transactional
указывает, что метод должен выполняться в транзакции. Менеджер транзакций открывает новую транзакцию и создаёт для неё экземпляр Session
, который доступен через sessionFactory.getCurrentSession()
. Все методы, которые вызываются в методе с данной аннотацией, также имеют доступ к этой транзакции, потому что экземпляр Session является переменной потока (ThreadLocal
). Вызов sessionFactory.openSession()
откроет совсем другую сессию, которая не связана с транзакцией.
Параметр rollbackFor
указывает исключения, при выбросе которых должен быть произведён откат транзакции. Есть обратный параметр — noRollbackFor
, указывающий, что все исключения, кроме перечисленных, приводят к откату транзакции.
Параметр propagation
самый интересный. Он указывает принцип распространения транзакции. Может принимать любое значение из перечисления org.springframework.transaction.annotation.Propagation
.
Propagation.REQUIRED
— выполняться в существующей транзакции, еслиPropagation.MANDATORY
— выполняться
в существующей транзакции, если она есть, иначе генерироватьPropagation.SUPPORTS
— выполняться в существующейPropagation.NOT_SUPPORTED
— всегда выполняться вне транзакции. ЕслиPropagation.REQUIRES_NEW
— всегда выполняться в новой независимой
транзакции. Если есть существующая, то она будет остановлена до
окончания выполнения новой транзакции. Propagation.NESTED
— если есть текущая транзакция, выполняться в новой, так называемой,
вложенной транзакции. Если вложенная транзакция будет отменена, то
это не повлияет на внешнюю транзакцию; если будет отменена внешняя
транзакция, то будет отменена и вложенная. Если текущей транзакции
нет, то просто создаётся новая. Propagation.NEVER
— всегда выполнять
вне транзакции, при наличии существующей генерировать исключение.Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
ищу помощи по правильному формированию списков характеристик товара, остановился на отображении в виде таблицы, однако имею неприятность...
при выборе вариативного товара в woocommerce, надпись очистить неправильно отображается, плывет https://apphoneru/product/iphone-xs-max-512gb-zolotoj/ хотя вот на этом...
Приложение формирует эксель-файл и сохраняет файл в папке на сервереНеобходимо отобразить его в браузере (т