@Transactional
Это аннотация, которую мы вряд ли сможем избежать при использовании Spring.Эта аннотация в основном используется для объявления транзакций. Его принцип реализации заключается в использовании Spring AOP для вплетения оператора реализации управления транзакциями до и после метода оформления аннотаций, поэтому разработчикам нужно использовать только одну аннотацию, чтобы заменить ряд утомительных задач кодирования, таких как запуск и закрытие транзакции.
Метод кодирования действительно прост, но поскольку интуитивно понятная логика реализации скрыта, некоторые неправильные методы кодирования могут привести к@Transactional
Аннотация недействительна и не может достичь эффекта транзакции. Самое прямое проявление — выбрасывается исключение при выполнении метода, но транзакция не откатывается, что в итоге приводит к генерации грязных данных.
Я также написал интересное обсуждение в своем блоге доПозвольте задать вопрос: будет ли откатываться эта транзакция?, многие люди далистандартный неправильный ответ, Если вы этого не видели, почему бы вам не пойти и не бросить вызов?
Хотя некоторые особые ситуации обсуждались ранее, все еще есть небольшие партнеры, которые будут задавать некоторые вопросы о сбоях транзакций в электронных письмах и группах WeChat. В основном все еще@Transactional
Способов объявить транзакцию недействительной действительно много! Итак, сегодня я напишу статью, чтобы обобщить ее.Если я столкнусь с этим снова в следующий раз, я открою эту статью и просматриваю одну за другой, чтобы увидеть, есть ли ошибка. Конечно, здесь могут быть упущения, поэтому, если у вас есть другие случаи ошибок, дайте мне знать, и я продолжу систематизировать их в этой статье.
1. Звоните в тот же класс
Случай ошибки:
public class A {
public void methodA() {
methodB();
// 其他操作
}
@Transactional
public void methodB() {
// 写数据库操作
}
}
Этот тип ошибки применяется ко всем аннотациям, реализованным на основе Spring AOP, например:«Использование @Async для реализации асинхронных вызовов»упоминается в@Async
аннотация,«Использование @Scheduled для реализации запланированных задач»упоминается в@Scheduled
заметки иИспользование аннотаций кэша Springупоминается в@Cacheable
Заметки и т. д.
Способ решения этой проблемы относительно прост, лучше разумно спланировать иерархические отношения, например так:
@Service
@AllArgsConstructor
public class A {
private B b;
public void methodA() {
b.methodB();
// 其他操作
}
}
@Service
public class B {
@Transactional
public void methodB() {
// 写数据库操作
}
}
Уведомление: Здесь класс A использует конструктор для внедрения реализации B (почему это бесполезно?@Autowrire
, вы можете взглянуть на это, опубликованное несколько дней назадКогда не следует вводить @Autowired), конструктор использует Lombok@AllArgsConstructor
Сгенерировать (если вы с этим не знакомы, можете прочитать предыдущую статьюЛомбок: сделать код JAVA более элегантным).
2. Модифицированный метод @Transactional не является общедоступным
Случай ошибки:
public class TransactionalMistake {
@Transactional
private void method() {
// 写数据库操作
}
}
Это также требование для аннотаций, реализованных на основе Spring AOP. Это самое простое, легкое для понимания и интуитивно понятное, поэтому я не буду его подробно описывать. Измените тип доступа к методу непосредственно наpublic
Вот и все.
3. Различные источники данных
Случай ошибки:
public class TransactionalMistake {
@Transactional
public void createOrder(Order order) {
orderRepo1.save(order);
orderRepo2.save(order);
}
}
Иногда мы можем писать несколько источников данных одновременно в одной операции, например, в приведенном выше примере.orderRepo1
а такжеorderRepo2
связаны два разных источника данных. По умолчанию такие транзакции между источниками данных не будут успешными.
Если вы хотите реализовать транзакции между несколькими источниками данных, вы можете ввести JTA, Если вы хотите это сделать, вы можете увидеть предыдущий обмен.«Использование JTA для управления транзакциями нескольких источников данных»
4. Неправильная конфигурация исключений отката
По умолчанию толькоRuntimeException
а такжеError
Сделайте откат. Если они и их потомки не являются исключениями, они не будут откатываться.
Поэтому при настройке исключений следует выполнить соответствующее планирование.Если вы хотите повлиять на откат транзакций, вы можете определить его какRuntimeException
подкласс ; если нетRuntimeException
, но также хотите вызвать откат, то вы можете использоватьrollbackFor
свойство, чтобы указать исключение для отката.
public class TransactionalMistake {
@Transactional(rollbackFor = XXXException.class)
public void method() throws XXXException {
}
}
5. Механизм базы данных не поддерживает транзакции
Это пример из отзывов читателей.Код точно такой же как и у меня.Моя сторона хороша,но он просто не откатывается.
Позже выяснилось, что пропущена конфигурация ключевого атрибута:
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
здесьspring.jpa.database-platform
Конфигурация в основном используется для установки диалекта, используемого спящим режимом. Здесь специально используется MySQL5InnoDBDialect, в основном для того, чтобы при использовании Spring Data JPA Hibernate использовал механизм хранения InnoDB при автоматическом создании таблиц, иначе для построения таблиц будет использоваться механизм хранения по умолчанию MyISAM, а механизм хранения MyISAM не имеет транзакций.
Если ваша транзакция не вступила в силу, вы можете посмотреть в созданной таблице, используется ли механизм хранения MyISAM, если да, то причина в этом!
резюме
Если вы видите конец и обнаружите, что есть другие ситуации, которые не были рассмотрены, сообщите нам об этом, и мы продолжим обновлять эту статью! В помощь читателям, столкнувшимся с такими проблемами.
Что ж, сегодняшнее обучение здесь! Если вы столкнулись с трудностями в процессе обучения? может присоединиться к нашему супер высокому качествуГруппа весеннего технического обмена, участвовать в обменах и обсуждениях, лучше учиться и прогрессировать!
Приглашаю обратить внимание на мой публичный номер: Программист ДД, поделитесь галантереей и мыслями, которых не видно снаружи!