1. Enable transaction support

Only need through @ EnableTransactionManagement annotations can open declarative transaction support, provide the optional values are:

  • proxyTargetClass: indicates whether an AOP proxy is interface-based or class-based,The defaultIs based on interface proxy.
  • mode: Can be used if there is an interfacePROXYCan be used if there is no interfaceASPECTJusingCgLibMake enhancements to classes.
  • order: Specifies the order in which transactions are intercepted, with the lowest priority by default, so that other proxy classes are guaranteed to execute after the transaction is started.

2. @Transactional

Once Transactional annotation support is turned on, you can add the @Transactional annotation to any class or method you want. The @Transactional annotation also has Settings.

2.1 transactionManager

The default is DataSourceTransactionManager.

2.2 the propagation

The propagation mechanism for transactions, which is REQUIRED by default, is that multiple method calls share the same transaction.

2.3 the isolation

The isolation level of the transaction, which depends on the database being used, is the default isolation level of the database.

2.4 the timeout

Transaction timeout.

2.5 readOnly

Whether it is read-only.

2.6 rollbackFor

The transaction is rolled back if an exception thrown in a class or method and an exception instanceof specified in rollbackFor returns true.

2.7 rollbackForClassName

Similar to rollbackFor, except that the name of the exception is specified.

2.8 noRollbackFor

The transaction is not rolled back when the specified exception is encountered

2.9 noRollbackForClassName

Similar to noRollbackFor, except that the name of the exception is specified.

3. The proxy object is not executed

In Spring, a declarative transaction is a proxy for a class. If it is a proxy class, you need to call the proxy class to execute the enhanced method. If you call the proxy class from within the method, you do not go to the proxy method or do not enhance the method, for example:

@Component public class FooServiceImpl implements FooService { @Override @Transactional(rollbackFor = RollbackException.class) public void insertThenRollback() throws RollbackException { this.jdbcTemplate.execute("INSERT INTO FOO (BAR) values('BBB')"); throw new RollbackException(); } @Override public void invokeInsertThenRollback() throws RollbackException { this.insertThenRollback(); }}Copy the code
@Override
public void run(String... args) throws Exception {
    try {
        this.fooService.invokeInsertThenRollback();
    } catch (RollbackException e) {
        // ignore.
    }
    log.info("bbb: {}.", this.countByBAR("BBB"));
}
Copy the code

The following output is displayed:

bbb: 1.
Copy the code

We can solve this problem in the following ways:

3.1 Calling its instance from the current proxy object

@Override
public void invokeInsertThenRollback() throws RollbackException {
  ((FooService) AopContext.currentProxy()).insertThenRollback();
}
Copy the code

3.2 Injecting its own instance

@Autowired
private FooService fooService;
​
@Override
public void invokeInsertThenRollback() throws RollbackException {
  this.fooService.insertThenRollback();
}
Copy the code

3.3 Add another layer of transactions

@Override
@Transactional(rollbackFor = RollbackException.class)
public void invokeInsertThenRollback() throws RollbackException {
    this.insertThenRollback();
}
Copy the code

4. The target method cannot be enhanced

Transactional Transactional methods can only support public decorators, otherwise transactions will fail

@Autowired
private FooServiceImpl fooService;
​
public void invokeInsertThenRollback() throws RollbackException {
    this.fooService.insertThenRollback();
}
Copy the code
@Transactional(rollbackFor = RollbackException.class)
protected void insertThenRollback() throws RollbackException {
    this.jdbcTemplate.execute("INSERT INTO FOO (BAR) values('BBB')");
    throw new RollbackException();
}
Copy the code

RollbackException and thrown exceptions return false

The @Transactional annotation defaults rollback exceptions to RuntimeException levels. This means that the transaction is not rolled back if it encounters a checked exception:

public class RollbackException extends Exception {
}
Copy the code
@Transactional
public void insertThenRollback() throws RollbackException {
    this.jdbcTemplate.execute("INSERT INTO FOO (BAR) values('BBB')");
    throw new RollbackException();
}
Copy the code
public void invokeInsertThenRollback() throws RollbackException {
    this.fooService.insertThenRollback();
}
Copy the code

6. Selection of progagtion

For example, the following methods return a BBB of 1, one of which is rolled back, and one of which is successfully executed.

@Override
@Transactional(rollbackFor = RollbackException.class,propagation = Propagation.REQUIRES_NEW)
public void insertThenRollback() {
    this.jdbcTemplate.execute("INSERT INTO FOO (BAR) values('BBB')");
}
​
@Override
@Transactional(rollbackFor = RollbackException.class)
public void invokeInsertThenRollback() throws RollbackException {
    this.jdbcTemplate.execute("INSERT into FOO (BAR) values('BBB')");
    this.fooService.insertThenRollback();
    throw new RollbackException();
}
Copy the code