предисловие
Всем привет, я Фей Чао. Я видел круг друзей такого фаната некоторое время назад
В чем польза AQS? Это действительно только для интервью?
Конечно, нельзя сказать, что AQS бесполезен, если вы не занимаетесь разработкой инфраструктуры или промежуточного ПО, вам сложно ощутить мощь AQS. Конечно, много раз в обучении необходима положительная обратная связь.Я слишком много узнал о строительстве ракет, и я больше не могу их использовать после интервью.Естественно, трудно иметь мотивацию продолжать учиться. Итак, аудитория большая, даже студенты CRUD могут пользоваться, и они любят спрашивать во время интервью.Самое главное, что когда есть проблема, не просто искать точки знаний для ответа? (Старые поклонники Фей Чао знают, что этот последний пункт очень важен для Фей Чао.)
Итак, это то, о чем Фей Чао упоминал ранее.Spring事务传播机制
.
Почему механизм распространения транзакций Spring?
Причина очень проста, потому что, если эти три условия могут быть выполнены, первое, о чем думает Фей Чао, это механизм распространения транзакций Spring, У него есть несколько условий.
1. Студенты CRUD обычно больше всего занимаются делами. Тем более, что раз с делами проблемы, то это взрывная порча, в этом можно не сомневаться
2. Интервьюируйте высокочастотные тестовые сайты, обычно также спрашивайте数据库的隔离级别
. Но Фэй Чао обнаружил, что многие ученики ставят数据库的隔离级别
иSpring的事务传播机制
Эти два понятия перепутаны, на самом деле это две разные вещи. В то же время есть и относительно известный вопрос на собеседовании: «Выполните 51 операцию, первые 50 раз успешны, 51-й — неудачно, как представить предыдущие 50 успешных раз, а 51-й неудачный откат». Если вы не знаете механизм распространения транзакций в Spring, то вы не имеете ни малейшего представления об этой проблеме, потому что многие студенты обычно имеют дело только с двумя случаями: все фиксируются и все откатываются.
3. Даже если вы где-то читали статьи о похожем механизме распространения транзакций Spring, это не проблема для обычных ситуаций, но если у вас есть модели с несколькими попытками, вы все равно не представляете, можно ли откатиться, грубо говоря. ты так и не понял принцип!
4. Конечно, самое главное, что Фэй Чао обещал всем написать это раньше, и он не хотел быть отморозком.
Базовые концепты
Механизм распространения транзакций Spring имеет следующие семь типов.
PROPAGATION_REQUIRED
: уровень распространения Spring по умолчанию.Если в контексте есть транзакция, добавляется текущая транзакция, а если транзакции нет, выполняется новая транзакция.
PROPAGATION_SUPPORTS
: присоединиться к текущей транзакции, если в контексте есть транзакция, и выполнить ее нетранзакционным способом, если транзакции нет.
PROPAGATION_MANDATORY
: Этот уровень распространения требует, чтобы транзакция существовала в контексте, иначе будет выдано исключение.
PROPAGATION_REQUIRES_NEW
: этот уровень распространения будет создавать новую транзакцию каждый раз, когда она выполняется, и одновременно приостанавливать транзакцию в контексте и возобновлять транзакцию в контексте после выполнения текущего потока. (Результат выполнения дочерней транзакции не влияет на выполнение и откат родительской транзакции)
PROPAGATION_NOT_SUPPORTED
: приостанавливать текущую транзакцию, когда в контексте есть транзакция, и возобновлять контекстную транзакцию после выполнения текущей логики. (Уменьшите размер транзакции и оберните неосновную логику выполнения для выполнения.)
PROPAGATION_NEVER
: Этот уровень распространения требует, чтобы в контексте не существовало транзакций, иначе будет выдано исключение.
PROPAGATION_NESTED
: Вложенная транзакция, если в контексте есть транзакция, она будет выполнена вложенной, а если ее нет, будет создана новая транзакция. (концепция точки сохранения)
Туманно ли после прочтения этих семерых? Верно! Откровенно говоря, запоминать эти семь типов особого смысла для вас нет, и большинство из них запоминаются. вPROPAGATION_REQUIRED
Эта ситуация по умолчанию является той, которую мы используем чаще всего, в основном покрывая 90% ситуаций, то есть обычная ситуация совместного отката. ДругойPROPAGATION_REQUIRES_NEW
. В принципе, если вы освоили эти два, то с 95% случаев проблем вообще нет, а если проблемы все же есть, то можете еще раз проверить эти семь и найти тот, который вам подходит.
Пример объяснения
Если это просто список понятий, то особого смысла в нем нет, поэтому для ответов на вопросы мы используем метод экзаменационно-ориентированного обучения, который является лучшим способом проверки мастерства.
Случай 1: Обычная ситуация
Это самая распространенная ситуация
@Transactional
@Override
public void Example1(User user) {
userMapper.insert(user);
propagationService.required();
}
@Transactional
@Override
public void required() {
throw new NullPointerException("肥朝假装抛出了异常");
}
модульный тест
@Test
public void testExample1() throws Exception {
User user = new User();
user.setName("微信公众号:肥朝");
userService.Example1(user);
}
Случай 2: требуется попытка
Пришло время ударить по доске и сосредоточиться. Эта ситуация также является одной из самых распространенных ситуаций для всех. Однако, поскольку попытка завершена, исключение не будет выдано. Итак, может ли эта вставка вставить данные?
@Transactional
@Override
public void Example2(User user) {
userMapper.insert(user);
try {
propagationService.required();
} catch (Exception e) {
e.printStackTrace();
}
}
@Transactional
@Override
public void required() {
throw new NullPointerException("肥朝假装抛出了异常");
}
модульный тест
@Test
public void testExample2() throws Exception {
User user = new User();
user.setName("微信公众号:肥朝");
userService.Example2(user);
}
Случай 3: try-requiresNew
Этот случай очень похож на предыдущий, разница в том, что уровень изоляции здесьPropagation.REQUIRES_NEW
тогда может эта вставка вставляет данные?
@Transactional
@Override
public void Example3(User user) {
userMapper.insert(user);
try {
propagationService.requiresNew();
} catch (Exception e) {
e.printStackTrace();
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void requiresNew() {
throw new NullPointerException("肥朝假装抛出了异常");
}
модульный тест
@Test
public void testExample3() throws Exception {
User user = new User();
user.setName("微信公众号:肥朝");
userService.Example3(user);
}
Случай 4: Обычная ситуация
Это очень похоже на первый случай, будет ли результат другим? Можно ли вставить последнюю вставку?
@Transactional
@Override
public void Example4(User user) {
userMapper.insert(user);
propagationService.requiresNew();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void requiresNew() {
throw new NullPointerException("肥朝假装抛出了异常");
}
модульный тест
@Test
public void testExample4() throws Exception {
User user = new User();
user.setName("微信公众号:肥朝");
userService.Example4(user);
}
Расшифровка и объяснение принципа на просторечии
Дело номер один
Излишне говорить, что любой, у кого есть немного здравого смысла в Java, знает, что исключение неизбежно приведет к откату, и база данных не будет вставлять данные.
Случай 2
Будет ли это вставлять данные? Ведь это исключение пробовали. В это время нормальное мышление будет думать, что данные могут быть вставлены нормально, но ответ таков, что данные не будут вставлены и будет выброшено исключение
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
Почему это так?
Случай 3
Это очень похоже на второй случай, потому что с тенью второго случая вы в это время становитесь неуверенными. Ответ заключается в том, что данные могут быть вставлены нормально.
Случай 4
Это очень похоже на случай 1. Первоначально вы были очень уверены, сможете ли вы вставить данные, но после тени случая 3 вы снова стали неуверенными в это время. Ответ: никакие данные не будут вставлены.
принцип!
Эти четыре случая были тщательно отобраны Фей Чао. Если вы знакомы с этими четырьмя случаями и принципами, вы будете знать, будет ли откатываться транзакция в различных сложных моделях попыток. Так вы думаете, что публичный аккаунт, который говорит вам обратить внимание на Фей Чао, причиняет вам боль?是爱你啊老哥!
Давайте сначала посмотрим@Transactional
основной метод
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// 开启事务
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// 执行业务方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 回滚事务
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
// 提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
Мы сосредоточимся на анализе случаев два и три. Давайте интерпретируем значение двух механизмов распространения транзакций:
PROPAGATION_REQUIRED
: уровень распространения Spring по умолчанию.Если в контексте есть транзакция, добавляется текущая транзакция, а если транзакции нет, выполняется новая транзакция.
PROPAGATION_REQUIRES_NEW
: этот уровень распространения будет создавать новую транзакцию каждый раз, когда она выполняется, и одновременно приостанавливать транзакцию в контексте и возобновлять транзакцию в контексте после выполнения текущего потока.
Сначала рассмотрим второй случай, реализациюExample2
При использовании метода из вышеизложенного известно, что транзакция будет открыта, а затем выполняться до тех пор, покаrequired
метод, в настоящее время, из-за используемого уровня изоляции по умолчанию, в это время он будет добавлен к транзакции только сейчас, а затемrequired
В методе произошло исключение, посмотрим
completeTransactionAfterThrowing(txInfo, ex);
основной метод в
отdoSetRollbackOnly(status)
Ты знаешь это слово,required
, транзакция настроена наRollbackOnly
, так хоть попробуй жил, ноExample2
Когда отправка завершена, обнаруживается, что она не может быть отправлена, поэтому информация об исключении выглядит следующим образом:
Transaction rolled back because it has been marked as rollback-only
Картинка стоит тысячи слов, я использую картинку, чтобы описать эти отношения.
Тогда почему в случае три вы можете снова вставить данные? Или используйте картинку для описания
требует внимания
@Transactional
Есть много моментов, на которые стоит обратить внимание
-
Если метод A вызывается для вызова метода B в том же классе, метод B не будет запускать транзакцию, и, естественно, механизм распространения транзакций не будет использоваться. Этот принцип будет проанализирован в продолжении Fei Dynasty.Конечно, если вы даже не знаете, что означает это предложение, фальшивые фанаты будут забиты!
-
@Transactional по умолчанию, только откат
RuntimeException
. Если исключение, которое вы выбрасываете, неRuntimeException
, что может привести к отклонениям от значения по умолчанию
Конечно, есть так много моментов, на которые следует обратить внимание, поэтому очень важно обратить внимание на последующий принципиальный анализ.
напиши в конце
Какие? Вы тоже хотите сами испытать на себе процесс решения задач из основного исходного кода? Нет проблем, Фей Чао подготовил для вас демонстрацию, добавьте друга Фей Чао в WeChat (WeChat: feizai_php) и [No Routine] поделитесь адресом, чтобы сообщить вам.