1. Основные принципы транзакций
Суть пружинных транзакций на самом деле заключается в поддержке базы данных транзакций. Без поддержки транзакций базы данных Spring не может предоставить функции транзакции. Для рабочих баз данных JDBC, если вы хотите использовать транзакции, вы можете выполнить следующие шаги:
1. Получите соединение Connection Con = DriverManager.getConnection ()
2. Откройте транзакцию con.setautocommit (true/false);
3. выполнить CRUD
4. Commit Transaction / Oflback Transaction con.commit () / con.rollback ();
5. Закройте соединение conn.close ();
После использования функции управления транзакциями Spring мы больше не можем писать код в шагах 2 и 4, но будут автоматически выполнены Spirng. Итак, как Spring открывается и закрывает транзакции до и после CRUD, которую мы пишем? Решая эту проблему, мы можем понять принцип реализации управления транзакциями весны в целом. Позвольте мне кратко представить метод аннотации в качестве примера
1. Включите драйвер аннотации в файле конфигурации и идентифицируйте его, аннотируя @Transactional в соответствующих классах и методах.
2. Когда начнется пружина, он будет проанализировать и генерировать связанные бобы. В настоящее время он будет проверять классы и методы с соответствующими аннотациями и генерировать прокси для этих классов и методов, а также выполняет связанную конфигурацию на основе соответствующих параметров @Transaction, так что соответствующие транзакции обрабатываются для нас в прокси (начинайте нормальные транзакции и транзакции с обратными исключениями).
3.
2. Распространенные свойства пружинных транзакций
Так называемый атрибут распространения пружинных транзакций определяет, как пружина должна обрабатывать поведение нескольких транзакций, когда они существуют одновременно. Эти свойства определены в транзакции. Конкретные константы объясняются в следующей таблице:
Iii. Уровень выделения базы данных
Грязное чтение: одна транзакция добавляет, удаляет и модифицирует данные, но не предана, а другая транзакция может считывать незавершенные данные. Если первая транзакция возвращается в это время, вторая транзакция считывает грязные данные.
Нет повторяющегося чтения: две операции чтения происходят в одной транзакции. Между первой операцией чтения и второй операцией другая транзакция изменяет данные. В настоящее время данные считываются два раза непоследовательны.
Чтение фэнтези: первая транзакция изменяет данные в определенном диапазоне партий, а вторая транзакция добавляет одну данных в этот диапазон. В настоящее время первая транзакция потеряет модификацию недавно добавленных данных.
Суммировать :
Чем выше уровень изоляции, тем больше он может обеспечить целостность и согласованность данных, но тем больше влияние на производительность параллелизма.
Уровень выделения по умолчанию в большинстве баз данных читается, например, SQLServer и Oracle
Уровень изоляции по умолчанию нескольких баз данных: повторяется чтение, например: mysql Innodb
IV Уровень изоляции весной
V. Гнездование транзакций
Благодаря вышеупомянутым теоретическим знаниям мы примерно понимаем некоторые атрибуты и характеристики транзакций баз данных и пружинных транзакций. Далее мы анализируем некоторые вложенные сценарии транзакций, чтобы глубоко понять механизм распространения пружинной транзакции.
Предположим, метод A () службы внешней транзакции вызывает метод B () внутренней службы b
PREAGATION_REQUID (Spring Default)
Если уровень транзакции serviceB.methodb () определяется как Propagation_Required, то, когда выполняется Servicea.methoda (), транзакция уже началась в пружине. В настоящее время называется ServiceB.MethoDB (). ServiceB.methodb () видит, что он работает в транзакции Servicea.methoda (), и никакая новая транзакция не началась.
Если ServiceB.MethoDB () работает, он назначит транзакцию себе.
Таким образом, если исключение происходит в Servicea.methoda () или в любом месте Serviceb.methodb (), транзакция будет откатана.
Propagation_Requires_New
Например, мы разработали, что Servicea.methoda () имеет уровень транзакции распространения.
Затем, когда выполняется ServiceB.MethoDB (), транзакция, в которой находится Servicea.methoda (), будет приостановлена, и ServiceB.MethoDB () запустит новую транзакцию и будет продолжать выполняться после завершения транзакции ServiceB.MethoDB ().
Разница между его транзакциями и распространением - это степень отката транзакции. Поскольку ServiceB.MethoDB () является новой транзакцией, существует две разные транзакции. Если ServiceB.methodb () был представлен, то Servicea.methoda () не сможет откатиться, serviceb.methodb () не откажется. Если ServiceB.MethoDB () не удается обратно, если исключение, которое выдвинуто Servicea.methoda (), будет пойман, транзакция Servicea.methoda () может быть все еще представлена (в основном зависит от того, является ли исключение, которое B -исключение является откатом, будет откат).
Распространение_SUPPORTS
Предполагая, что уровень транзакции serviceb.methodb () является распространением_Supports, когда она выполняется в serviceb.methodb (), если будет обнаружено, что Servicea.methoda () открыла транзакцию, она присоединится к текущей транзакции. Если обнаружено, что Servicea.methoda () не запустила транзакцию, она не запускает саму транзакцию. В это время транзакция внутреннего метода полностью зависит от самой внешней транзакции.
Распространять_nested
Ситуация теперь становится все более сложной. Свойство транзакции ServiceB.MethoDB () настроено как Propagation_Nested. Как эти два будут сотрудничать в это время? ServiceB#methodb Если откат, то внутренние транзакции (т.е. ServiceB#methodb) откатится обратно в точку сохранения, прежде чем он выполняется, в то время как внешние транзакции (то есть Servicea#Methoda) могут иметь следующие два способа обработки:
а Поймайте исключения и выполнить логику филиала исключений
void methoda () {try {serviceb.methodb (); } catch (someException) {// выполнять другие предприятия, такие как servicec.methodc (); }} Этот метод также является наиболее ценной вещью в вложенных транзакциях. Это играет роль исполнения филиала. Если ServiceB.MethoDB не выполняется, то Servicec.methodc () выполняется, и ServiceB.MethoDB откатился обратно в точку сохранения до его выполнения, поэтому не генерируются грязные данные (эквивалентно этому методу никогда не выполняется). Эта функция может быть использована в некоторых специальных службах, и ни Propagation_Required, ни Propagation_Requires_New не могут сделать это.
беременный Внешняя транзакция отката/кода коммита не вносит никаких изменений. Если внутренняя транзакция (ServiceB#methodB), то сначала ServiceB.MethoDB возвращается в точку сохранения, прежде чем он выполнится (в любом случае), и внешняя транзакция (т.е. Servicea#Methoda) решит, будет ли он совершать или откат на основе конкретной конфигурации.
Остальные три атрибута распространения транзакций в основном неэффективны, поэтому здесь нет анализа.
6. Резюме
Для мест, где транзакции необходимы в проекте, я полагаю, что разработчики должны использовать интерфейс Spring TransactionCallback для реализации транзакций. Не используйте аннотации с пружинной транзакцией. Если вы должны использовать аннотации, вы должны иметь подробное понимание механизма распространения и уровня изоляции пружинных транзакций, в противном случае могут возникнуть неожиданные эффекты.