web123456

Spring Boot's transaction management annotation @EnableTransactionManagement usage

Spring Boot is very simple to use transactions. First, use the annotation @EnableTransactionManagement to enable transaction support, and then add annotation @Transactional to the Service method that accesses the database.

Regarding the transaction manager, whether it is JPA or JDBC, it implements self-interface PlatformTransactionManager. If you add the spring-boot-starter-jdbc dependency, the framework will inject the DataSourceTransactionManager instance by default. If you add the spring-boot-starter-data-jpa dependency, the framework will inject the JpaTransactionManager instance by default.

You can add the following method to the startup class, Debug test, and you can know which implementation class of the PlatformTransactionManager interface is automatically injected.

@EnableTransactionManagement // Enable annotation transaction management, which is equivalent to the xml configuration method <tx:annotation-driven />
@SpringBootApplication
public class ProfiledemoApplication {

    @Bean
    public Object testBean(PlatformTransactionManager platformTransactionManager){
        (">>>>>>>>>>" + ().getName());
        return new Object();
    }

    public static void main(String[] args) {
        (, args);
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

These SpringBoots are automatically done for us, and these are not transparent to us. If your project is done large and you add more persistence dependencies, we will still choose to artificially specify which transaction manager to use.
The code is as follows:

@EnableTransactionManagement
@SpringBootApplication
public class ProfiledemoApplication {

    // where the dataSource framework will automatically inject us
    @Bean
    public PlatformTransactionManager txManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public Object testBean(PlatformTransactionManager platformTransactionManager) {
        (">>>>>>>>>>" + ().getName());
        return new Object();
    }

    public static void main(String[] args) {
        (, args);
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

In Spring containers, we manually annotate @Bean will be loaded first, and the framework will not re-instrate other PlatformTransactionManager implementation classes.

Then in Service, the method annotated by @Transactional will support transactions. If the annotation is on a class, all methods of the entire class support transactions by default.

For how to deal with multiple transaction managers in the same project, please see the example below. For details, please see the comments in the code.

@EnableTransactionManagement // Turn on annotation transaction management, which is equivalent to <tx:annotation-driven /> in the xml configuration file
@SpringBootApplication
public class ProfiledemoApplication implements TransactionManagementConfigurer {

    @Resource(name="txManager2")
    private PlatformTransactionManager txManager2;

    // Create transaction manager 1
    @Bean(name = "txManager1")
    public PlatformTransactionManager txManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    // Create Transaction Manager 2
    @Bean(name = "txManager2")
    public PlatformTransactionManager txManager2(EntityManagerFactory factory) {
        return new JpaTransactionManager(factory);
    }

    // Implement the interface TransactionManagementConfigurer method, whose return value represents the transaction manager used by default if you have multiple transaction managers
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return txManager2;
    }

    public static void main(String[] args) {
        (, args);
    }

}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

@Component
public class DevSendMessage implements SendMessage {

    // Use value to specify which transaction manager to use
    @Transactional(value="txManager1")
    @Override
    public void send() {
        (">>>>>>>>Dev Send()<<<<<<<<");
        send2();
    }

    // In the case of multiple transaction managers, if you use value to specify it
    // The default method annotationDrivenTransactionManager() returns the transaction manager
    @Transactional
    public void send2() {
        (">>>>>>>>Dev Send2()<<<<<<<<");
    }

}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

Note:
If there are multiple PlatformTransactionManager instances in the Spring container and the interface TransactionManagementConfigurer is not implemented to specify the default value, when we use the annotation @Transactional on the method, we must specify it with value. If it is not specified, an exception will be thrown.

When the system needs to provide default transaction management, implement the interface TransactionManagementConfigurer specification.

For some systems, in order to avoid unnecessary problems, the value value of @Transactional must be clearly specified in the business. It is not recommended to implement the interface TransactionManagementConfigurer, so that the console will explicitly throw exceptions and developers will not forget to actively specify them.