I Was Scolded by the Boss Because I Didn’t Add rollbackfor = Exception.Class to @Transactional

开发/后端 · 阅读 1242 · 点赞 0

内容转载于 https://medium.com/javarevisited/i-was-scolded-by-the-boss-because-i-didnt-add-rollbackfor-exception-class-to-transactional-68cbeaea28a0

What Happens If the @transactional Annotation Does Not Add Rollbackfor = Exception.Class?

First prepare a piece of data in Mysql

Start testing

Let’s test @Transactional first, everyone knows that 2/0 will throw an exception. The code is as follows.

@Transactional
public Response<Void> updateMedium(UserVO userVO){

    UserDomain userDomain = this.getIfPresent(userVO.getId());
    userDomain.setDeleted(userVO.getDeleted());
    UserDomain saved = userRepository.save(userDomain);
    int a = 2 / 0;

    return Response.success();
}

Execute the test UserDomain saveddeleted=0 indicates that the update is successful, don’t worry, let’s continue to breakpoint and go below.

As expected, an error was reported when int a = 2 / 0, and a java.lang.ArithmeticException: /by zero appeared

That the exception class ArithmeticException inherits RuntimeException

The exception that @Transactional rolls back by default is RuntimeException

We click into the RuntimeException class to find out. We find that RuntimeException inherits Exception and all exception classes basically inherit RuntimeException including the java.lang.ArithmeticException exception just above.

So as long as the exception thrown by the subclasses of RuntimeException and RuntimeException @Transactional can be rolled back.

At this time, let’s see if the value of the database has been modified successfully. Obviously, the data has been rolled back.

Let’s try adding an exception to @Transactional’s code and see what happens? Code show as below.

@Transactional
public Response<Void> updateMedium(UserVO userVO) throws Exception {

    UserDomain userDomain = this.getIfPresent(userVO.getId());
    userDomain.setDeleted(userVO.getDeleted());
    userDomain.setPassword(userVO.getPassword());
    userDomain.setUsername(userVO.getUsername());
    userDomain.setCreateTime(new Date());
    UserDomain saved = userRepository.save(userDomain);
    try {
        int a = 2 / 0;
    } catch (Exception e) {
        throw new Exception();
    }

    return Response.success();
}

We directly use try catch to catch exceptions and then custom throw Exception exceptions in catch.

The exception thrown directly is the java.lang.Exception exception we specified. Let’s take a look at the database.

The database deleted has been updated to 0, indicating that @Transactional cannot roll back Exception

Finally

@Transactional can only rollback exceptions thrown by subclasses of RuntimeException and RuntimeException, and cannot rollback Exception exceptions.

It is recommended that everyone use @Transactional(rollbackFor = Exception.class) scenarios

  • If you need to support rollback Exception
  • If it is to add, delete or modify here

Some invalid scenarios of @Transactional(rollbackFor = Exception.class)

  • Not modified with public
  • The try catch catches the exception (no exception is thrown manually in the catch)
  • No @Service is added (that is, it is not managed by Spring)

Thanks for reading. I am looking forward to your following and reading more high-quality articles.

内容转载于 https://medium.com/javarevisited/i-was-scolded-by-the-boss-because-i-didnt-add-rollbackfor-exception-class-to-transactional-68cbeaea28a0