When use the spring transaction has a main switch @ EnableTransactionManagement

1. Transaction manager

Spring Boot is very simple to use transactions

  1. After using annotations @ EnableTransactionManagement open transaction support
  2. You can annotate @Transactional on the Service method that accesses the database

About the transaction manager, whether JPA or JDBC PlatformTransactionManager implements the interface.

  1. If you add a spring – the boot – starter – JDBC dependence, framework will inject DataSourceTransactionManager instance by default.
  2. If you add a spring-boot-starter-data-jPA dependency, the framework will inject the JpaTransactionManager instance by default.

2. Which transaction manager is loaded?

@EnableTransactionManagement // Annotate transaction management, equivalent to XML configuration < 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); }}Copy the code

3. Manually specify which transaction manager to use

SpringBoot does this automatically for us. It’s not transparent to us. If your project is big and you add a lot of persistence dependencies, we’ll still choose to manually specify which transaction manager to use. The code is as follows:

@EnableTransactionManagement
@SpringBootApplication
public class ProfiledemoApplication {
	 
	// The dataSource framework will inject it automatically
	@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); }}Copy the code
  • In the Spring container, we manual annotation @ Bean will be priority load, frame not to instantiate the other PlatformTransactionManager implementation class.
  • Then in a Service, methods annotated by @Transactional support transactions. If the annotation is on a class, all methods of the entire class support transactions by default.

4. Choice of multiple transaction managers

For an example of how to handle multiple transaction managers in the same project, see comments in the code.

@EnableTransactionManagement // Enable annotation transaction management, 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);
	}
	 
	/ / implementing an interface TransactionManagementConfigurer method, the return value represents in having multiple transaction manager under the condition of default to the transaction manager
	@Override
	public PlatformTransactionManager annotationDrivenTransactionManager(a) {
		return txManager2;
	}
	 
	public static void main(String[] args) { SpringApplication.run(ProfiledemoApplication.class, args); }}Copy the code

The above defines two transaction manager, including annotationDrivenTransactionManager () method returns the default transaction manager. AnnotationDrivenTransactionManager () this method be TransactionManagementConfigurer methods defined in the interface. The source code is as follows:

public interface TransactionManagementConfigurer {

	/**
	 * Return the default transaction manager bean to use for annotation-driven database
	 * transaction management, i.e. when processing {@code @Transactional} methods.
	 * <p>There are two basic approaches to implementing this method:
	 * <h3>1. Implement the method and annotate it with {@code @Bean}</h3>
	 * In this case, the implementing {@code @Configuration} class implements this method,
	 * marks it with {@code @Bean}, and configures and returns the transaction manager * directly within the method body: * <pre class="code"> * &#064; Bean * &#064; Override * public PlatformTransactionManager annotationDrivenTransactionManager() { * return new DataSourceTransactionManager(dataSource()); * }</pre> * <h3>2. Implement the method without {@code @Bean} and delegate to another existing
	 * {@code @Bean} method</h3> * <pre class="code"> * &#064; Bean * public PlatformTransactionManager txManager() { * return new DataSourceTransactionManager(dataSource()); *} * * &#064; Override * public PlatformTransactionManager annotationDrivenTransactionManager() { * return txManager(); // reference the existing {@code @Bean} method above
	 * }</pre>
	 * If taking approach #2, be sure that <em>only one</em> of the methods is marked
	 * with {@code @Bean}!
	 * <p>In either scenario #1 or #2, it is important that the
	 * {@code PlatformTransactionManager} instance is managed as a Spring bean within the
	 * container since most {@code PlatformTransactionManager} implementations take advantage
	 * of Spring lifecycle callbacks such as {@code InitializingBean} and
	 * {@code BeanFactoryAware}. Note that the same guidelines apply to
	 * {@code ReactiveTransactionManager} beans.
	 * @return a {@link org.springframework.transaction.PlatformTransactionManager} or
	 * {@link org.springframework.transaction.ReactiveTransactionManager} implementation
	 */
	TransactionManager annotationDrivenTransactionManager(a);

}
Copy the code

The following uses two transaction managers:

@Service
public class DevSendMessageServiceImpl implements SendMessageService {
 
	// Specify which specified transaction manager to use with value
	@Transactional(value="txManager1")
	@Override
	public void send(a) {
		System.out.println(">>>>>>>>Dev Send()<<<<<<<<");
		send2();
	}
	 
	// In the case of multiple transaction managers, if value is not specified
	/ / the default usage annotationDrivenTransactionManager () returns the transaction manager, such as in this case txManager2
	@Transactional
	public void send2(a) {
		System.out.println(">>>>>>>>Dev Send2()<<<<<<<<"); }}Copy the code

5. To summarize

To get a clear idea of the transaction manager, we know from the above example what the transaction manager says:

  1. After using annotations @ EnableTransactionManagement open transaction support
  2. You can annotate @Transactional on the Service method that accesses the database
  3. You can either introduce the starter or specify which transaction manager to use.