Detail the use of Spring Boot transactions

  • 2020-06-19 10:22:27
  • OfStack

spring Boot USES transactions very simply, starting with the @EnableTransactionManagement annotation to enable transaction support, and then adding the @Transactional annotation to the Service method to access the database.

As for the transaction manager, JPA, JDBC and so on implement the self-interface PlatformTransactionManager. If you add an ES11en-ES12en-ES13en-ES14en dependency, the framework will inject DataSourceTransactionManager instances by default. If you add spring-ES17en-ES18en-ES19en-ES20en dependencies, the framework will inject JpaTransactionManager instances by default.

You can add the following method, Debug test, to the boot class to see which implementation class of the PlatformTransactionManager interface is automatically injected.


@EnableTransactionManagement //  Initiate annotation transaction management, equivalent to xml Configurational  <tx:annotation-driven />
@SpringBootApplication
public class ProfiledemoApplication {
 @Bean
 public Object testBean(PlatformTransactionManager platformTransactionManager){
 System.out.println(">>>>>>>>>>" + platformTransactionManager.getClass().getName());
 return new Object();
 }
 public static void main(String[] args) {
 SpringApplication.run(ProfiledemoApplication.class, args);
 }
}

These SpringBoot are automated for us, they are not transparent to us, and if you are making a large project and adding more persistence dependencies, we will still choose which transaction manager to use artificially.

The code is as follows:


@EnableTransactionManagement
@SpringBootApplication
public class ProfiledemoApplication {
 //  Among them  dataSource  The framework will automatically inject for us 
 @Bean
 public PlatformTransactionManager txManager(DataSource dataSource) {
 return new DataSourceTransactionManager(dataSource);
 }
 @Bean
 public Object testBean(PlatformTransactionManager platformTransactionManager) {
 System.out.println(">>>>>>>>>>" + platformTransactionManager.getClass().getName());
 return new Object();
 }
 public static void main(String[] args) {
 SpringApplication.run(ProfiledemoApplication.class, args);
 }
}

In the Spring container, our manual annotation @Bean will be loaded first, and the framework will not reinstantiate the 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 an example of how to handle multiple transaction managers in the same project, see the following example and the comments in the code.


@EnableTransactionManagement //  Enable annotation transaction management, equivalent to xml In the configuration file  <tx:annotation-driven />
@SpringBootApplication
public class ProfiledemoApplication implements TransactionManagementConfigurer {
 @Resource(name="txManager2")
 private PlatformTransactionManager txManager2;
 //  Create a transaction manager 1
 @Bean(name = "txManager1")
 public PlatformTransactionManager txManager(DataSource dataSource) {
 return new DataSourceTransactionManager(dataSource);
 }
 //  Create a transaction manager 2
 @Bean(name = "txManager2")
 public PlatformTransactionManager txManager2(EntityManagerFactory factory) {
 return new JpaTransactionManager(factory);
 }
 //  Implementing an interface  TransactionManagementConfigurer  Method whose return value represents the transaction manager used by default when there are multiple transaction managers 
 @Override
 public PlatformTransactionManager annotationDrivenTransactionManager() {
 return txManager2;
 }
 public static void main(String[] args) {
 SpringApplication.run(ProfiledemoApplication.class, args);
 }
}

@Component
public class DevSendMessage implements SendMessage {
 //  use value Specify which transaction manager to use 
 @Transactional(value="txManager1")
 @Override
 public void send() {
 System.out.println(">>>>>>>>Dev Send()<<<<<<<<");
 send2();
 }
 //  In the case of multiple transaction managers, if used value specify 
 //  The default use method  annotationDrivenTransactionManager()  Returns the transaction manager 
 @Transactional
 public void send2() {
 System.out.println(">>>>>>>>Dev Send2()<<<<<<<<");
 }
}

Note:

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

The implementation interface TransactionManagementConfigurer is specified in cases where the system needs to provide default transaction management.

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

Reference reading:

Detail SpringBoot transaction management

Spring Boot Quick Start Guide

Spring Boot Quick start tutorial


Related articles: