Внутренняя транзакция не откатывается, когда их ошибка во внешнем trsansaction

#java #spring #spring-boot #transactions

Вопрос:

Я выполняю транзакцию в Spring boot. И у нас есть метод startTransfer, в котором у нас есть некоторая бизнес-логика, касающаяся проверки транзакции, и после этого транзакция сохраняется в базе данных с использованием метода DAO. После сохранения его в базе данных мы проверяем, работает сервер очереди сообщений или нет. Если сервер не работает, мы откатываем весь метод startTransfer, и база данных откатывается.

Вот метод startTransfer

 private static final MessageService messageService = new MessageService();

@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW, readOnly = false, timeout = 500, rollbackFor = Exception.class)
public void startTransfer(String receiverID, String amount, String label, String senderID) throws QueueDownException {
    
    // some business logic, in which we are checking the senders balance and creating an object of the txn class 

    dbTxnDao.saveTransaction(txn);   // txn is getting saved and not rollbacked on QueueServerException 

    if(!messageService.checkWorking()) {
        throw new QueueDownException("Kafka Queue not working in the startTransfer");
    }
}

 

checkWorking () — это еще один метод, который возвращает true, когда он работает иначе false.
это и есть Дао

 @Repository
@Transactional
public class DbTxnDAO {
    SessionFactory sessionFactory = new Configuration()
            .configure("hibernate.cfg.xml")
            .addAnnotatedClass(DbTxn.class)
            .buildSessionFactory();
    
    // method not getting rolled back
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.MANDATORY, readOnly = false, timeout = 500,  rollbackFor = Exception.class)
    public void saveTransaction(DbTxn txn) {
        Session session = sessionFactory.getCurrentSession();
        session.beginTransaction();
        session.save(txn);
        session.getTransaction().commit();
        session.close();
        return;
    }

}

 

Поэтому, когда метод checkWorking() возвращает false и мы вводим блок if, возникает исключение QueueDownException, и вся транзакция должна быть откатана. Но вместо этого dbTxnDao.saveTransaction(txn) не откатывается.

Как мне добиться отката saveTransaction

Комментарии:

1. Есть ли причина, по которой вам нужно самостоятельно управлять сеансом гибернации?

2. На самом деле все сущности Dao, Dto уже были разработаны другим программистом

3. Дело в том, что вы смешиваете управление транзакциями Spring ( @Transaction аннотацию) с программным управлением транзакциями, которое обрабатывается вами внутри кода с аннотациями @Transaction . Мой первый подход состоял бы в том, чтобы избавиться от программного управления транзакциями, если у вас нет веских причин для его сохранения.