Откат транзакции не прерывается при возникновении ошибки во вложенном методе

#java #mysql #hibernate #spring-boot #transactional

#java #mysql #переход в спящий режим #весенняя загрузка #транзакционный

Вопрос:

В моем недавнем проекте я столкнулся со сценарием, когда мне нужно откатить работу базы данных при возникновении ошибки во вложенном методе. Ранее я работал с @Transactional одним методом. В тот раз все сработало нормально. Но в текущем сценарии у меня есть зависимость от другого метода. Поэтому мне нужно выполнить откат при возникновении ошибки во вложенном методе. Я хочу выполнить откат в этом методе

 @Transactional
@Override
public String updateCustomOfficeHour(OfficeHour officeHour) {
    if (officeHour.getId() == null || officeHourRepository.getFirstById(officeHour.getId()) == null)
        throw new EntityNotFoundException("No Office-Hour found with this id");

    OfficeHour temp = officeHourRepository.getFirstById(officeHour.getId());
    List<OfficeHour> officeHours = officeHourRepository.findByFromDateAndToDate(temp.getFromDate(), temp.getToDate());

    List<OfficeHour> tempList = new ArrayList<>();
    for (OfficeHour officeHourObj : officeHours) {
        officeHourObj.setDeleted(true);
        tempList.add(officeHourObj);
    }
    officeHourRepository.saveAll(tempList);
    this.createCustomOfficeHour(officeHour);
    return "Updated Custom-Office-Hour";
}
  

Здесь у меня есть операция с базой данных в строке officeHourRepository.saveAll(tempList);
Мне нужно выполнить откат при возникновении ошибки в методе this.createCustomOfficeHour(officeHour); . Этот метод

    @Transactional
    @Override
    public String createCustomOfficeHour(OfficeHour officeHour) {
        if (officeHour.getFromDate() == null || officeHour.getToDate() == null
                || officeHour.getFirstOutTime() == null || officeHour.getLastInTime() == null
                || officeHour.getInTime() == null || officeHour.getOutTime() == null)
            throw new EntityNotFoundException("Null value received for OfficeHour fields!");

        if (officeHour.getToDate().compareTo(officeHour.getFromDate()) < 0)
            throw new EntityNotFoundException("FromDate is Getter than ToDate");

        if (officeHourRepository.isFromDateExist(officeHour.getFromDate()).longValue() > 0
                || officeHourRepository.isToDateExist(officeHour.getToDate()).longValue() > 0) {
            throw new EntityNotFoundException("FromDate/ToDate is already assigned");
        }

        if (officeHourRepository.isDateExistsBetweenFromAndToDate(officeHour.getFromDate(), officeHour.getToDate()).longValue() > 0)
            throw new EntityNotFoundException("Office Hour Already Assigned In This Range");


        for (int i = 1; i <= count; i  ) {
           ........
           ........
           ........
           officeHourRepository.save(obj);

        }
        return "Custom Office-Hour Created";
    }
  

И это мой Exception класс

 public class EntityNotFoundException extends RuntimeException {

    public EntityNotFoundException(String message) {
        super(message);
    }
}
  

Я также добавил spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect в application.properties

Любая помощь будет оценена.

Ответ №1:

Ваше EntityNotFoundException исключение не проверяется и соответствует документам spring:

Поведение Spring по умолчанию для декларативного управления транзакциями соответствует соглашению EJB (откат выполняется автоматически только для непроверенных исключений)

транзакция должна быть откатана по умолчанию.

Это связано с тем, что updateCustomOfficeHour и createCustomOfficeHour обрабатываются в рамках одной транзакции (здесь нет переопределения распространения, поэтому используется значение по умолчанию REQUIRED).

Вы могли бы добавить явный откат для вашего исключения в updateCustomOfficeHour методе, но это в любом случае должно быть избыточным:

 @Transactional(rollbackFor = {EntityNotFoundException.class})
  

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

1. Я добавил @Transactional(rollbackFor = {EntityNotFoundException.class}) на updateCustomOfficeHour , но получаю красное предупреждение для rollbackFor . Это показывает Cannot resolve method 'rollbackFor' . Что мне теперь делать?

2. Если вы используете, org.springframework.transaction.annotation.Transactional должно быть rollbackFor @AvijitBarua

3. @ShafinMahmud я получил rollBackOn , но это не сработало.

4. Попробуйте установить @Transactional(распространение = Propagation. ОБЯЗАТЕЛЬНО) во внутреннем методе.

5. @MaciejKowalski Я установил @Transactional(propagation = Propagation.REQUIRED) вкл createCustomOfficeHour и установил @Transactional(rollbackFor = {EntityNotFoundException.class}) вкл updateCustomOfficeHour . Но, к сожалению, не получил ожидаемого результата.