javaspringspring-boottransactionsspring-transactions

Spring Transaction Rollback


I have functions, and this functions will go on catch conditions. My expectations whenever it goes to catch conditions it should've rollback the previous save data. but why the data is still saved on the DB without rollback. even i already use annotation @Transactional

@Transactional
public RpaLog createRpaLogObject(CreateRpaLogObjectRequest request) {
    RpaLog rpaLog = new RpaLog();
    try {
        rpaLog.setFunctionName(request.getFunctionName());
        rpaLog.setStatus(request.getStatus());
        rpaLog.setCreatedDate(HelperUtils.getCurrentTimestamp());
        rpaLog = rpaLogRepository.save(rpaLog);

        String externalApiUrl = rpaConfig.getEndpoint() + rpaLog.getId();
        restTemplate.getForObject(
                externalApiUrl,
                ExternalApiResponse.class
        );
    }catch (Exception e){
        throw new CreationFailedException(MessageConstants.RPA_CREATION_FAILED + request.getFunctionName());
    }

    return rpaLog;
}

i used Spring Data Commons - CrudRepository package by the way. How can i achieve the rollback ?

I've test like this also to force the rollback, but it seems doesnt trigger the rollback at all

@Transactional(rollbackFor = Exception.class)
public RpaLog createRpaLogObject(CreateRpaLogObjectRequest request) {
    RpaLog rpaLog = new RpaLog();
    rpaLog.setFunctionName(request.getFunctionName());
    rpaLog.setStatus(request.getStatus());
    rpaLog.setCreatedDate(HelperUtils.getCurrentTimestamp());
    rpaLog = rpaLogRepository.save(rpaLog);

    throw new RuntimeException("Throw example");
}

Solution

  • Try to modify your code like following:

    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public RpaLog createRpaLogObject(CreateRpaLogObjectRequest request) {
        // your code
    }
    
    

    To test if the rollback works, simulate an exception in the try block (e.g., by throwing a RuntimeException) and check if the data is rolled back in the database.

    Update: By default, the @Transactional annotation will only roll back transactions for unchecked exceptions (i.e., subclasses of RuntimeException). If your CreationFailedException is a checked exception, the transaction will not roll back automatically.

    Also: Consider the isolation level of your transaction. If it's set to a level that prevents visibility of uncommitted changes, it might affect how rollbacks are perceived. You can specify the isolation level in the @Transactional annotation.