Основным исследованием в этой статье является распространение сделок с весенними транзакциями и принципы ее реализации, которые представлены следующим образом.
В настоящее время Spring является де -факто стандартом для разработки Java, благодаря его удобству, полным функциям и простым в использовании. В процессе разработки работа DB является очень распространенной операцией, и когда дело доходит до DB, он включает в себя транзакции. Во время нормального процесса разработки транзакций, даже если вы не заметите это, не будет никаких побочных эффектов на нормальное выполнение программы. Однако, если происходит исключение и транзакция не обрабатывается должным образом, могут возникнуть неожиданные результаты. Весна инкапсулировала различные операции с точки зрения транзакций, особенно появление декларативных транзакций, что делает разработку более комфортным. Spring расширяет транзакции и поддерживает определение множественных атрибутов распространения, что также является в центре внимания этой статьи.
Не строго говоря, транзакция - это аббревиатура нескольких операций. Эти операции либо вступают в силу, либо ни один из них не вступит в силу (эквивалентно не выполняется). Общий процесс работы упрощается следующим образом:
try {connection conn = getConnection (); // Выполнить некоторые операции базы данных} Catch (Exception e) {conn.rollback ();} наконец {conn.close ();}Некоторые проблемы можно увидеть из приведенного выше кода:
Spring предоставляет декларативные транзакции, поэтому нам не нужно обращать внимание на конкретную реализацию базового уровня, и блокирует множество различных деталей реализации базового уровня. Чтобы поддерживать тонкий контроль транзакций несколькими сложными предприятиями, Spring обеспечивает атрибуты распространения транзакций и в сочетании с декларативными транзакциями, она стала основным инструментом транзакций.
В классе TransactionDefinition Spring обеспечивает 6 свойств распространения, которые объясняются простыми примерами.
Теплое напоминание: следующее упомянутое соединение текущей транзакции относится к использованию одного и того же соединения внизу, но объект состояния транзакции может быть воссоздан и не влияет на него. В статье упоминается, что в настоящее время существует только одна транзакция, что означает, что базовое соединение является общим и не заботится о том, сколько создается объекты состояния транзакции (TransactionStatus).
Описание: Если транзакция уже существует, тогда присоединяйтесь к транзакции. Если транзакции нет, создайте транзакцию. Это значение атрибута распространения по умолчанию.
Давайте посмотрим на небольшой пример, код заключается в следующем:
@TransactionalPublic void service () {servicea (); serviceb ();}@transactionalservicea ();@transactionalserviceb ();Servicea и ServiceB оба объявляют транзакции. По умолчанию, распространение = Propagation_Required. В течение всего процесса сервисного вызова существует только одна общая транзакция. Когда произойдет любое исключение, все операции будут откатаются.
Описание: Если транзакция уже существует, присоединяйтесь к транзакции, в противном случае создается так называемая пустая транзакция (ее можно считать, что она не является выполнением транзакции).
Давайте посмотрим на небольшой пример, код заключается в следующем:
public void service () {servicea (); бросить новый runtimeexception ();}@transactional (распространение = распространение. Supports) servicea ();В настоящее время не существует транзакции, когда выполняется Servicea, поэтому исключение, добавленное в службу, не приведет к откату Servicea.
Давайте посмотрим на другой маленький пример, код заключается в следующем:
public void service () {servicea ();}@transactional (распространение = распространение. DO SQL 2}Поскольку у Servicea нет транзакций при запуске, в настоящее время, если основной источник данных Defaultautocommit = true, то SQL1 эффективен. Если defaultautocommit = false, то SQL1 недействителен. Если у сервиса есть тег @transactional, Servicea делится транзакциями обслуживания (больше не полагается на Defaultautocommit). В настоящее время Servicea все откатывается.
Описание: в настоящее время должна существовать транзакция, в противном случае будет брошено исключение.
Давайте посмотрим на небольшой пример, код заключается в следующем:
public void service () {serviceB (); Servicea ();} serviceB () {do SQL} @Transactional (Propagation = Propagation.Mandatory) Servicea () {do SQL}В этом случае выполнение службы вызовет исключение. Если defaultautocommit = true, ServiceB не откатится назад. Если defaultautocommit = false, выполнение ServiceB будет недействительным.
ПРИМЕЧАНИЕ. Если в настоящее время существует транзакция, сначала инкапсулируйте текущее содержание, связанное с транзакцией, в объект, то воссоздайте новую транзакцию, примите эту сущность в качестве параметра и используйте его для восстановления транзакции. Более тупым утверждением является приостановка текущей транзакции (транзакция не требуется) и создать новую транзакцию. В этом случае между этими двумя транзакциями не существует зависимости, и новая транзакция может быть отменена назад, но внешняя транзакция продолжает выполняться.
Давайте посмотрим на небольшой пример, код заключается в следующем:
@TransActionAlPublic void service () {serviceB (); try {servicea (); } catch (Exception e) {}} serviceb () {do sql} @Transactional (Propagation = Propagation.Requires_New) servicea () {do sql 1 1/0; DO SQL 2}При вызове сервисного интерфейса, поскольку Servicea использует Tress_new, он создаст новую транзакцию. Однако, поскольку Servicea бросает исключение времени выполнения, Servicea откатается. В методе обслуживания исключения пойманы, поэтому ServiceB представляет нормально. Обратите внимание, что попытка ... Код поймать в сервисе необходим, в противном случае служба вызовет исключение, в результате чего сервис будет откат.
ПРИМЕЧАНИЕ. Если в настоящее время существует транзакция, приостановите текущую транзакцию, а затем новый метод выполняется в среде без транзакций и в среде без пружинных транзакций, коммит SQL полностью зависит от значения свойства DefaultAutoCommit.
Давайте посмотрим на небольшой пример, код заключается в следующем:
@TransActionAlPublic void service () {serviceB (); servicea ();} serviceb () {do sql} @transactional (ropagation = opragation.not_supported) servicea () {do sql 1 1/0; DO SQL 2}Когда метод сервиса вызывается, исключение выкладывается при выполнении кода 1/0 в методе Servicea. Поскольку Servicea находится в среде без транзакций, эффективен ли SQL1, зависит от значения Defaultautocommit. Когда defaultautocommit = true, SQL1 эффективен, но ServiceB будет откат обратно, потому что служба бросает исключение.
Описание: Если в настоящее время присутствует транзакция, исключение брошено, в противном случае код выполняется в среде без транзакций.
Давайте посмотрим на небольшой пример, код заключается в следующем:
public void service () {serviceB (); servicea ();} serviceb () {do sql} @transactional (Propagation = Propagation.never) servicea () {do sql 1 1/0; DO SQL 2}После приведенного выше примера Service, если Defaultautocommit = true, метод ServiceB и SQL1 в Servicea вступят в силу.
Примечание. Если в настоящее время существует транзакция, используйте технологию SavePoint для сохранения текущего состояния транзакции, а затем базовый уровень разделяет соединение. Когда возникает ошибка внутри вложенной, она сама по себе будет возвращаться в состояние SavePoint. Пока исключение поймано снаружи, оно может продолжать совершать внешние транзакции, не будучи нарушаемым встроенным бизнесом. Однако, если исключение бросается внешней транзакцией, вся большая транзакция будет откатана.
ПРИМЕЧАНИЕ. Диспетчер транзакций на конфигурации пружины должен активно указывать NestEdTransActionAllowed = true, как показано ниже:
<bean id = "datatransactionmanager"> <name = "dataSource" ref = "dataDataSource" /> <name = "nestEdTransActionAllowed" value = "true" /> < /bean>
См. Небольшой пример, код заключается в следующем:
@TransactionalPublic void service () {servicea (); try {serviceb (); } catch (Exception e) {}} servicea () {do sql} @TransActional (Propagation = Propagation.nested) serviceB () {do sql1 1/0; do sql2}ServiceB - это встроенный сервис, и исключение выполнения выполняется внутри, поэтому ServiceB откатится. Поскольку услуга поймала исключение, Servicea может представлять его обычно.
Давайте посмотрим на другой пример, код заключается в следующем:
@TransactionalPublic void service () {servicea (); ServiceB (); 1/0;}@Transactional (Propagation = opragation.nested) servicea () {do sql} serviceb () {do sql}Поскольку служба бросает исключение, весь метод обслуживания будет откат. (Это отличается от Propagation_Requires_new. Встроенные службы в разделе «Вложенный режим» будут отменены исключениями из внешних транзакций.)
Приведенные выше примеры иллюстрируют несколько атрибутов распространения, предоставленных весенними транзакциями, используются для удовлетворения различных потребностей бизнеса, которые могут быть определены бизнесом. Далее, давайте посмотрим на то, что наиболее важные технические зависимости от весеннего реализуют эти атрибуты распространения. В этом разделе перечислены Propagation_Requires_New и Propagation.Nested для кратких описаний соответственно.
Следующий кодовый вызов:
@TransActionAlPublic void service () {serviceB (); try {servicea (); } catch (Exception e) {}}@Transactional (Propagation = Propagation.Requires_New) servicea () {do sql 1 1/0; do sql 2} serviceb () {do sql}Схема исполнения следующая:
а Создайте объект состояния транзакции, получите новое соединение, сбросьте автосмит, извлечение, тайм -аут и другие свойства соединения
беременный Свяжите соединение с переменной Threadlocal
в В ожидании текущей транзакции, инкапсуляции объекта состояния текущего состояния транзакции, соединения и другой информации в объект SurvendedResources, который можно использовать для восстановления
дюймовый Создайте новый объект состояния транзакции, повторно новое соединение, сбросьте автоматическую коммит, выбросы, тайм -аут и другие свойства нового соединения. В то же время, сохраните объект ShousedResources для восстановления транзакций и связывайте новое соединение с переменной Threadlocal (операция перезаписать)
эн. Поймайте исключение, откатайте соединение в Threadlocal, восстановите параметры соединения, закройте соединение и восстановите подсветренные сечения
фон Отправьте соединение в переменной Threadlocal (вызывая отправку ServiceB), восстановите параметры соединения, закройте соединение и верните соединение с источником данных
Таким образом, результат выполнения программы заключается в том, что Servicea откатится, и ServiceB успешно представлен.
Следующий кодовый вызов:
@TransactionalPublic void service () {servicea (); try {serviceb (); } catch (Exception e) {}} servicea () {do sql} @TransActional (Propagation = Propagation.nested) serviceB () {do sql1 1/0; do sql2}Схема исполнения следующая:
а Создайте объект состояния транзакции, получите новое соединение, сбросьте автосмит, извлечение, тайм -аут и другие свойства соединения
беременный Свяжите соединение с переменной Threadlocal
в Отметьте использование текущего объекта состояния транзакции, получить объект Threadlocal Connection, сохранить точку сохранения текущего соединения и используется для восстановления исключения. В настоящее время точка сохранения является статусом после выполнения Servicea
дюймовый Поймайте исключение и используйте SavePoint в C для отката от транзакции, то есть откатайте состояние в состояние после выполнения Servicea. Все выполнения методов обслуживания не вступают в силу
эн. Получить объект соединения в Threadlocal, отправлять транзакции, восстановить свойства соединения, закрыть соединение
Основываясь на базовом источнике данных, Spring использует Threadlocal, SavePoint и другие технические точки для реализации различных атрибутов распространения транзакций, что облегчает реализацию различных сложных услуг. Только понимание принципа атрибутов распространения, мы можем лучше контролировать пружинные транзакции. Пружинные операции с откатом полагаются на захват исключений. По умолчанию транзакции будут откатаются только в том случае, если будут выброшены Runtimeexception и ошибка. Конечно, это можно настроить. Для получения дополнительной информации вы можете проверить @transactional Annotation.
Весенние декларативные транзакции приносят нам большое удобство. Чтобы хорошо использовать это оружие, все еще необходимо понять основные принципы. Эта статья - только вершина айсберга весенних транзакций. Читатели могут подробно изучить на этой основе.
Вышеупомянутое содержимое этой статьи о распространении транзакций весенних транзакций и принципах ее реализации. Я надеюсь, что это будет полезно для всех. Заинтересованные друзья могут продолжать ссылаться на другие связанные темы на этом сайте. Если есть какие -либо недостатки, пожалуйста, оставьте сообщение, чтобы указать это. Спасибо, друзья, за вашу поддержку на этом сайте!