Spring transaction management and failure scenarios

Transaction isolation level and transaction propagation reference: https://blog.csdn.net/sumengnan/article/details/112620349

One, programmatic affairs

Manual programming is required to implement transactions, and the granularity can be controlled to the code block level

(1) Original transaction management method

The three key interfaces: TransactionDefinition, PlatformTransactionManager , TransactionStatus

1, TransactionDefinition (transaction definition interface)

The default implementation class is DefaultTransactionDefinition. Used to define the static properties of a transaction. For example, transaction propagation behavior, timeout period, etc. You can customize the class to implement the Transactiondefinition interface.

2, PlatformTransactionManager (transaction manager interface)

The implementation class is as follows:

According to different ORM frameworks, it is mainly divided into the following categories:

  • DateSourceTransactionManager: Suitable for JDBC and iBatis persistence operations.
  • HibernateTransactionManager: suitable for Hibernate framework
  • JpaTransactionManager: suitable for using JPA persistent operations
  • JtaTransactionManager: suitable for distributed transaction operations
  • other

3. TransactionStatus: (Transaction Status Interface)

TransactionStatus inherits the SavepointManager interface, and SavepointManager is an encapsulation of the above-mentioned savepoint function in the transaction.

Usage: Return the TransactionStatus object through the PlatformTransactionManager.getTransaction(...) method. Provides a simple method to control transaction execution and query transaction status. For example, whether it is a new transaction, whether it has been marked for rollback

Code example:

	@Autowired
	private PlatformTransactionManager dataSourceTransactionManager;				
//-------------------------------------------------------分割,上面是注入,下面是关键代码
            TransactionStatus transactionStatus=null;
				try {
					transactionStatus = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());//手动开启事务
					//此处进行业务操作
					dataSourceTransactionManager.commit(transactionStatus);//提交
				} catch (Exception e) {
					if(StringMoreUtils.checkValNotNull(status)){
						dataSourceTransactionManager.rollback(transactionStatus);//回滚
					}
					e.printStackTrace();
				}	

 

(2) TransactionTemplate template mode (recommended)

In fact, it is an encapsulation of the original transaction management method above, and the inheritance relationship is as follows:



TransactionTemplateWhen mainly relying on the TransactionTemplate.execute( ... ),execution of transaction management, there are two options for the incoming parameters:
1. TransactionCallback(There is a return value
2. TransactionCallbackWithoutResult(There is no return value

Code example:

//有返回值
      transactionTemplate.execute(new TransactionCallback<Object>() {
            @Override
            public Object doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //.......   业务代码
                    return new Object();//有返回值
                } catch (Exception e) {
                    //回滚
                    transactionStatus.setRollbackOnly();
                    return null;
                }
            }
        });
//无返回值
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                try {
                    // ....  业务代码
                } catch (Exception e){
                    //回滚
                    transactionStatus.setRollbackOnly();
                }

            }
        });

Two, declarative affairs

Through the aop method, the granularity can only be controlled to the method level

(1) Configure via xml, based on tx and aop namespace

    <!-- 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 配置 transactionTemplate -->
    <bean id="transactionTemplate"
          class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager">
            <ref bean="transactionManager"/>
        </property>
    </bean>
     < tx:advice  id ="txAdvice"  transaction-manager ="transactionManager" >
         < tx:attributes >
             < tx:method  name ="*"  propagation ="REQUIRED"   />
         </ tx:attributes >
     </ tx:advice >
    
     < aop:config >
         < aop:pointcut  id ="interceptorPointCuts"
            expression ="execution(* com.bluesky.spring.dao.*.*(..))"   />
         < aop:advisor  advice-ref ="txAdvice"
            pointcut-ref ="interceptorPointCuts"   />         
     </ aop:config >   

(2) Declare transactions through @Transaction annotations (recommended)

    @Transactional
    public List<SysUser> findByLogin(String username, String password) {
        return this.sysUserRepository.findByLogin(username, password);
    }

 

3. The principle of @Transaction annotation:

For example: I call the findByLogin method of service

1. When the project starts, spring will create an instance of JpaTransactionManager (under the  springboot-autoconfiguration package)

There are also transaction interceptors (at the dynamic proxy level, not the springmvc one)

 

2. When the spring ioc container is initialized at the same time, a dynamic proxy class will be created for my service class, through the following class

3. When the method of the service class is called, the invoke method of the proxy class JdkDynamicAopProxy will be called first

Reflective call the proceed method of ReflectiveMethodInvocation

Then call the invoke method of the transaction interceptor

Then call the invokeWithinTransaction method of TransactionAspectSupport of the abstract parent class of TransactionInterceptor

Or the invokeWithinTransaction method, which saw the execute method in the familiar programmatic transaction, as well as classes such as JapTransactionManager and TransactionCallback .

Explain that the bottom layer of the declarative transaction is also the programmatic transaction used

截图中:invocation.proceedWithInvocation()方法,其实就是调用service的findByLogin这个方法

So far the transaction process is complete

 

Fourth, the scenario where the @Transaction annotation fails:

Tip: Spring recommends not to use @Transactional annotations in interfaces or interface methods, because only interface-based proxies will take effect.

(1) Transaction scenarios are not supported:

  1. The database MyIsam engine does not support transactions. After mysql5.5.5, the default is InnoDB engine to support transactions.
  2. @Transactional(propagation = Propagation.NOT_SUPPORTED) runs in non-transactional mode . Of course there will be no affairs.

(2) Not paying attention to the configuration level:

  1. The @EnableTransactionManagement annotation is not added to the startup class. (Annotations are added to the DataSourceTransactionManagerAutoConfiguration class of springboot-autoconfigure)
  2. The transaction class is not annotated with @Service. That is, it is not managed by spring (not dynamically proxied).
  3. The data source is not configured with a transaction manager. (Implementation classes of PlatformTransactionManager interface, such as JpaTransactionManager, datasourceTransactionManager)

(3) Not paying attention to the coding level:

  1. Annotations can only be used on public methods. If you want to use it on non-public methods, you can turn on  AspectJ proxy mode
  2. The exception is not thrown up. The ry-catch is caught and should be thrown to the proxy class. The upper proxy class will roll back after catching the exception.
  3. @Transactional(rollbackFor = Exception.class) The exception type is wrong. Note: RuntimeException exception is rolled back by default
  4. Self-call problem. Only when the service transaction method is called from the outside, will the dynamic proxy be used, and the transaction can be used. Calling other methods of this class will not use dynamic proxy

Four, @Transaction annotation interpretation of write transactions and read-only transactions:

The default is a read-write transaction, plus @Transactional (readOnly = true) becomes a read-only transaction.

(1) What is the function of read-only transactions?

  1. The orm framework improves performance. For example: hibernate eliminates the need to detect and synchronize object persistent updates (do not perform flush operations).
  2. DML statements are not allowed , otherwise an error will be reported.
  3. Suitable for reports or statistics. You can query multiple queries in the same transaction. When other transactions modify the data at the same time, the query results will not be affected

(2) How does the hibernate framework optimize read-only transactions?

The HibernateJpaDialect class is the key, and its beginTransaction method is to start the transaction operation

(3) How does mysql enable read-only transactions?

set transaction read only;

Open the read-only transaction at this point in time, and all subsequent queries are data at this point in time (all submissions of other transactions will not change the query results), until commit or rollBack or execute ddl statement.

set transaction read only; can only be the first statement of a read-only transaction, and it can only appear once. The following statements can only appear in select, select into, open, fetch, close, lock table, commit, rollback and other statements.

Nothing else can appear, such as update, or select * from table for update (add exclusive lock), etc.

 

 

 

 

Guess you like

Origin blog.csdn.net/sumengnan/article/details/112639564