How to set nestedTransactionAllowed to true in Spring?

716 views Asked by At

I have a case where I need to initiate calls to four different services in the same method. According to our business logic all four steps must succeed, rollback otherwise. The problem is that since all the steps occur in the same transaction (via @Transactional annotation) the second call in the method cant process the result of the first one. I have tried Propagation.REQUIRES_NEW on the first call but since it starts a new transaction the changes it makes are committed and not rollbacked whether the other calls succeed or not. At some point it seemed like Propagation.NESTED could do the work but I get a NestedTransactionNotSupportedException which warns me of setting the nestedTransactionAllowed property to true. But I could not found any document about how to do that. Any ideas? And also would appreciate any other suggestion for the problem. Thanks.

Root method:

@Override
    @Transactional
    public GuestUserDto createGuestUser(GuestUserRegisterRequest existingGuestUser) {
        guestUserDeactivationDelegateService.deactivateGuestUser(existingGuestUser);

        UserDto userDto = guestUserRegistrationDelegateService.registerGuestUser(
            guestUserRegisterDtoConverter.convert(existingGuestUser));

        createGuestUserAddress(existingGuestUser);

        guestUserRegisterHistoryService.createRegisterHistory(
            guestUserRegistrationHistoryDtoBuilder.build(userDto.getMemberId(), existingGuestUser));

        return guestUserDtoConverter.convert(userDto);
    }

Deactivation method:

    @Transactional
    public void deactivateGuestUser(GuestUserRegisterRequest existingUser) {
        deactivateSmsVerification(existingUser.getMemberId());
        
        String emailPlaceholder = existingUser.getMemberId() + existingUser.getEmail();
        userGraphClientService.updateUserStatus(createUserRequest(existingUser.getMemberId()));

        updateGuestUserStatus(existingUser.getMemberId(), emailPlaceholder);
    }
2

There are 2 answers

0
Erhan Cavdar On

Seems that the main cause was Hibernate's flush operations order, as it was giving priority to insert over update. Flushing manually after updating in DAO layer solved the problem.

0
Jalandar R On

NestedTransactionAllowed can be set in HibernateTransactionManager as follows.

    HibernateTransactionManager manager = new HibernateTransactionManager(sessionFactory);
    manager.setNestedTransactionAllowed(true);
    return manager;

Please refer to https://www.demo2s.com/java/spring-hibernatetransactionmanager-setnestedtransactionallowed-boolean.html