【问题标题】:Transaction Rollback is not heppening when error occour in nested method嵌套方法中发生错误时不会发生事务回滚
【发布时间】:2019-08-24 18:37:54
【问题描述】:

在我最近的项目中,我遇到了一个场景,当嵌套方法发生错误时,我需要回滚数据库操作。早些时候我在单一方法上使用@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);
    }
}

我还在application.properties中添加了spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

任何帮助将不胜感激。

【问题讨论】:

    标签: java mysql hibernate spring-boot transactional


    【解决方案1】:

    您的EntityNotFoundException 是一个未经检查的异常并遵循spring docs

    声明式事务管理的 Spring 默认行为如下 EJB 约定(仅在未经检查的异常上自动回滚)

    事务应该默认回滚。

    这是因为updateCustomOfficeHourcreateCustomOfficeHour 在同一个事务下处理(这里没有覆盖传播,所以使用默认的 REQUIRED)。

    您可以在 updateCustomOfficeHour 方法上为您的异常添加显式回滚,但无论如何这应该是多余的:

    @Transactional(rollbackFor = {EntityNotFoundException.class})
    

    【讨论】:

    • 我在updateCustomOfficeHour 上添加了@Transactional(rollbackFor = {EntityNotFoundException.class}),但我收到rollbackFor 的红色警报。它显示Cannot resolve method 'rollbackFor' 。我现在该怎么办?
    • 如果您使用的是org.springframework.transaction.annotation.Transactional,则应该有rollbackFor @AvijitBarua
    • @ShafinMahmud 我得到了rollBackOn,但没有用。
    • 尝试在内部方法上设置@Transactional(propagation = Propagation.REQUIRED)。
    • @MaciejKowalski 我将@Transactional(propagation = Propagation.REQUIRED) 设置在createCustomOfficeHour 上,并将@Transactional(rollbackFor = {EntityNotFoundException.class}) 设置在updateCustomOfficeHour 上。但不幸的是没有得到预期的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-17
    相关资源
    最近更新 更多