The spring service method throws a runtimeException but does not roll back

defines a service:UserService where a method is defined as follows:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveException(User user){
    userDao.save(user);
    throw new RuntimeException("");
}

if I call this method directly in the Controller layer, I can roll back, but if I wrap this method in another layer, it is as follows:


public void saveInnerException() {
    User user1 = new User();
    user1.setName("");
    this.saveException(user1);
}    

saveInnerException is still in the same service, and there is no transaction added to this method. At this time, if the Controller layer calls the saveInnerException method, the transaction will commit, which is strange. An exception has occurred and should be rolled back.
I did another test, and this time I redefined a service:UserService2, with a non-transactional method as follows:

public void test(){
    User user = new User();
    user.setName("");
    userService.saveException(user);
}   

if Controller calls the test method of UserService2, the transaction will be rolled back. There is also an extra layer of calls, why is the result different?

Mar.23,2021

it's not surprising that the
default Spring transaction is only valid (triggered) when it is called from the public method and is called by an external class, probably because when a proxy call is used, the corresponding transaction logic is executed before and after the call.
if it is an internal call, it cannot be executed normally through the proxy mode, that is, the related processing of the transaction has no effect.
there are also some other proxy implementations, such as @ Async


the problem lies in this
in the saveInnerException method
if you don't believe it, you will find that this is a normal example rather than an aop-enhanced

.
  • Redis transaction management

    when you use spring-data-redis to integrate redis, in a spring project and operate on redis through RedisTemplate, you want to package some operations of multiple redistemplate so that other Redis operations may not be inserted. public class Test { @R...

MySQL Query : SELECT * FROM `codeshelper`.`v9_news` WHERE status=99 AND catid='6' ORDER BY rand() LIMIT 5
MySQL Error : Disk full (/tmp/#sql-temptable-64f5-1e9936e-47513.MAI); waiting for someone to free some space... (errno: 28 "No space left on device")
MySQL Errno : 1021
Message : Disk full (/tmp/#sql-temptable-64f5-1e9936e-47513.MAI); waiting for someone to free some space... (errno: 28 "No space left on device")
Need Help?