Ответ
TransactionTemplate — это класс в Spring, предоставляющий программный (declarative) способ управления транзакциями. Он является альтернативой декларативному управлению через @Transactional и даёт больше контроля над границами транзакции.
Когда использовать?
- Когда нужен полный программный контроль над началом и завершением транзакции.
- Для выполнения нескольких операций в одной транзакции внутри одного метода.
- Когда логика коммита или отката зависит от условий, которые сложно выразить через
@Transactional.
Пример использования:
@Service
public class TransferService {
private final TransactionTemplate transactionTemplate;
public TransferService(PlatformTransactionManager transactionManager) {
this.transactionTemplate = new TransactionTemplate(transactionManager);
// Настройка параметров транзакции
this.transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
}
public void transferMoney(Long fromAccId, Long toAccId, BigDecimal amount) {
// Код внутри execute() выполняется в транзакции
transactionTemplate.execute(status -> {
Account from = accountRepository.findById(fromAccId).orElseThrow();
Account to = accountRepository.findById(toAccId).orElseThrow();
from.debit(amount);
to.credit(amount);
accountRepository.save(from);
accountRepository.save(to);
// Принудительный откат по условию
if (someCondition) {
status.setRollbackOnly();
}
return "Transfer completed"; // Возвращаемое значение
}); // Автоматический commit/rollback
}
}
Преимущества перед @Transactional:
- Точный контроль: Границы транзакции чётко видны в коде.
- Гибкость: Возможность динамически менять параметры (изоляция, распространение).
- Условный rollback: Легко вызвать
status.setRollbackOnly()в любом месте.
Недостаток: Код становится более многословным по сравнению с аннотацией @Transactional.
Ответ 18+ 🔞
Так, слушай сюда, про этот ваш TransactionTemplate. Это ж, блядь, как если бы вместо того, чтобы сказать «эй, Спринг, сделай мне тут всё в транзакции» (это @Transactional), ты сам берёшь руль в руки и говоришь: «Отъебись, я сам всё сделаю, от и до».
А когда это, блядь, нужно?
Представь, ты не просто хочешь обернуть метод в транзакцию, а тебе надо внутри одного метода, сука, нагородить кучу операций, да ещё и решать на ходу — коммитить это всё в БД или откатывать с грохотом. Или параметры транзакции у тебя меняются, как перчатки. Вот тогда ты и хватаешься за TransactionTemplate, как за спасательный круг.
Смотри, как это выглядит в деле:
@Service
public class TransferService {
private final TransactionTemplate transactionTemplate;
public TransferService(PlatformTransactionManager transactionManager) {
this.transactionTemplate = new TransactionTemplate(transactionManager);
// Тут ты настраиваешь свою боевую машину
this.transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
}
public void transferMoney(Long fromAccId, Long toAccId, BigDecimal amount) {
// Всё, что внутри execute() — это священная земля транзакции
transactionTemplate.execute(status -> {
Account from = accountRepository.findById(fromAccId).orElseThrow();
Account to = accountRepository.findById(toAccId).orElseThrow();
from.debit(amount);
to.credit(amount);
accountRepository.save(from);
accountRepository.save(to);
// А вот тут магия! Решаешь на ходу — пиздец транзакции или нет
if (someCondition) {
status.setRollbackOnly(); // Всё, поезд ушёл, откат, сука!
}
return "Transfer completed"; // Вернуть можешь что угодно
}); // А тут автоматом — либо коммит, либо откат в пизду
}
}
Чем он, блядь, крут?
- Контроль, как у Цербера: Ты сам видишь, где транзакция начинается и где кончается. Никаких сюрпризов из-за проксирования.
- Гибкость до охуения: Захотел другую изоляцию или propagation — хуяк, поменял настройку. Динамически, мать его!
- Условный пиздец: Захотел откатить —
setRollbackOnly(), и всё, приехали. Никаких сложных исключений выдумывать.
А минус-то в чём?
Да в том, что код становится длиннее, чем список грехов на исповеди. Писать @Transactional над методом — это раз плюнуть. А тут — целый ритуал с настройками и лямбдой. Но за контроль, блядь, всегда платишь многословностью, это как закон природы.