Первый вопрос. Какая связь существует между уровнем изоляции транзакций, параметрами 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 — всегда выполнять
вне транзакции, при наличии существующей генерировать исключение.Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости