-неизвестно

 -Поиск по дневнику

Поиск сообщений в ATUM

 -Подписка по e-mail

 

 -Постоянные читатели

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 17.02.2006
Записей:
Комментариев:
Написано: 1139


Без заголовка

+ в цитатник

Cообщение скрыто для удобства комментирования.
Прочитать сообщение


ATUM   обратиться по имени Понедельник, 29 Апреля 2013 г. 15:44 (ссылка)
Кроме директив отката, нужно указать также транзакционный атрибут, который определяет поведение транзакции. Платформа Java поддерживает шесть типов транзакционных атрибутов, независимо от того, используете вы EJB или Spring Framework:

Required
Mandatory
RequiresNew
Supports
NotSupported
Never
Описывая каждый из них, я буду использовать фиктивный метод methodA(), к которому и будет применяться транзакционный атрибут.

Если для метода methodA() указан транзакционный атрибут Required, и methodA() вызывается из существующей транзакции, будет использоваться область видимости существующей транзакции. В противном случае methodA() начнет новую транзакцию. Если транзакцию начал methodA(), то и завершать ее (фиксировать или откатывать) должен тоже methodA(). Это чаще всего применяемый транзакционный атрибут, используемый по умолчанию как в EJB 3.0, так и в Spring. К сожалению, во многих случаях он используется некорректно, что приводит к проблемам с целостностью и непротиворечивостью данных. Для каждой из транзакционных стратегий я в следующих статьях серии более подробно рассмотрю использование этого атрибута.

Если для метода methodA() указан транзакционный атрибут Mandatory, и methodA() вызывается из области видимости существующей транзакции, будет использоваться область видимости существующей транзакции. Однако если methodA() вызывается вне контекста транзакции, будет сгенерировано исключение Trans­ac­ti­on­RequiredException, указывающее, что транзакция уже должна существовать до вызова methodA(). Этот транзакционный атрибут используется в транзакционной стратегии Client Orchestration, описанной в следующем разделе этой статьи.

Интересен транзакционный атрибут RequiresNew. Я встречаюсь с неверным использованием или пониманием этого атрибута чаще, чем с верным. Если для methodA() указан транзакционный атрибут RequiresNew, и methodA() вызывается изнутри или извне контекста транзакции, methodA() всегда начинает (и заканчивает) новую транзакцию. Это значит, что если methodA() вызывается из контекста другой транзакции (например, Transaction1), Transaction1 будет приостановлена, и будет начата новая транзакция (Transaction2). После завершения methodA()Transaction2 будет зафиксирована или отменена, и возобновится исполнение Transaction1. Это, очевидно, нарушает свойства транзакций ACID (ACID – атомарность, непротиворечивость, изоляция, надежность), особенно атомарность. Другими словами, все обновления БД в этом случае уже не содержатся в одной единице работы. В случае отката Transaction1 изменения, внесенные Trans­action2, сохранятся. В таком случае, зачем нужен такой транзакционный атрибут? Как было показано в первой статье серии, этот транзакционный атрибут нужно использовать только при операциях над БД (например, аудите или логировании), независимых от нижележащих транзакций (в данном случае Transaction1).

Транзакционный атрибут Supports – еще один, который, я считаю, большинство разработчиков не совсем понимает или оценивает. Если для methodA() указан транзакционный атрибут Supports, и methodA() вызывается в контексте существующей транзакции, methodA() будет исполняться в контексте существующей транзакции. Если же methodA() вызывается вне контекста транзакции, новая транзакция не начинается. Этот атрибут в основном используется при операциях чтения из БД. Почему бы в этом случае не использовать транзакционный атрибут NotSupported (описанный в следующем абзаце)? В конце концов, этот атрибут гарантирует, что метод будет выполняться без использования транзакций. Ответ прост. Исполнение запроса в контексте существующей транзакции приведет к считыванию данных из лога транзакций БД (проще говоря, измененных данных), а при его исполнении вне контекста транзакции будут считаны неизмененные данные из таблицы. Например, если вы хотите вставить в таблицу Trade новый заказ и затем (в той же транзакции) получить список заказов, незафиксированный заказ будет присутствовать в списке. Но если бы вы использовали транзакционный атрибут NotSupported, запрос обращался бы к таблице, а не к логу транзакций. Таким образом, вы не увидели бы в списке незафиксированного заказа. Это не обязательно плохо, все зависит от бизнес-логики и конкретной ситуации.

Транзакционный атрибут NotSupported указывает, что вызываемый метод не будет использовать или начинать транзакцию, независимо от наличия таковой. Если для methodA() указан транзакционный атрибут NotSupported, и methodA() вызывается в контексте существующей транзакции, транзакция приостанавливается до окончания выполнения метода. После окончания выполнения метода исходная транзакции возобновляется. Есть всего несколько случаев использования этого транзакционного атрибута, и в основном они относятся к использованию хранимых процедур. Если вы пытаетесь вызвать хранимую процедуру из контекста существующей транзакции, и хранимая процедура содержит BEGIN TRANS или, в случае Sybase, исполняется в unchained-режиме, будет выдано исключение, указывающее, что новая транзакция не может быть начата в случае наличия уже существующей (проще говоря, что вложенные транзакции не поддерживаются). Почти все контейнеры используют Java Transaction Service (JTS) как реализацию транзакций для JTA по умолчанию. Это именно JTS – а не платформа Java как таковая – не поддерживает вложенных транзакций. Если нельзя изменить хранимую процедуру, можно использовать атрибут NotSupported, чтобы прервать существующую транзакцию и избежать фатального исключения. При этом, конечно, вы уже не сможете внести атомарные изменения в БД в той же LUW. Это компромисс, но он может быстро вытащить вас из затруднительной ситуации.

Транзакционный атрибут Never, возможно, самый интересный из всех. Он работает так же, как NotSupported, но с одной существенной разницей. Если при вызове метода с транзакционным атрибутом Never уже существует контекст транзакции, генерируется исключение, указывающее, что при вызове этого метода транзакции недопустимы. Единственный случай использования этого атрибута, который я смог придумать – тестирование. Он предоставляет простой и быстрый способ проверки наличия транзакции на момент вызова конкретного метода. Если вы используете транзакционный атрибут Never и получаете исключение при вызове проверяемого метода, значит, транзакция существует, и наоборот. Это хороший способ проверить, что ваша транзакционная стратегия работает.
Ответить С цитатой В цитатник
ATUM   обратиться по имени Понедельник, 29 Апреля 2013 г. 17:15 (ссылка)
http://www.k-press.ru/cs/2009/3/ts/ts.asp

Транзакционные стратегии
Ответить С цитатой В цитатник
 

Добавить комментарий:
Текст комментария: смайлики

Проверка орфографии: (найти ошибки)

Прикрепить картинку:

 Переводить URL в ссылку
 Подписаться на комментарии
 Подписать картинку