Spring study notes-06 declarative transaction

Let's review the transactions in the database: transactions have four characteristics-Atomicity, Consistency, Isolation, Durability, referred to as ACID.

Atomicity : A transaction is a logical unit of work in a database. The operations contained in the transaction either succeed or fail .

Consistency : The result of transaction execution must be to change the database from one consistent state to another consistent state. After the transaction is executed successfully, the database is in a consistent state. If an error occurs during execution and part of the modification made by the transaction has been written to the physical database, the database is in an inconsistent state.

Isolation : The execution of a transaction cannot affect the execution of other transactions. The internal operations and data used by a transaction are isolated from other transactions, and the concurrently executed transactions do not interfere with each other .

Persistence : Once a transaction is committed, its modification to the database is permanent , and other subsequent operations will not have any impact on the result of this modification.

Let's test the transaction of SqlSessionTemplate: adjust Dao to see the transaction through Service

UserService.java

package com.zt.Service;

public interface UserService {
    void testTransaction();
}

UserServiceImpl.java

package com.zt.Service.Impl;

import com.zt.Dao.UserDao;
import com.zt.Eneity.User;
import com.zt.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    public void testTransaction() {

        int i = userDao.addUser(new User(2,"zzt","zjm"));
        System.out.println(i);

        int j = 1 / 0;

        userDao.updateUserById(new User(2,"withstand","pain"));

    }
}

TestTranscation.java

import com.zt.Service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-config.xml")
public class TestTranscation {
    
    @Autowired
    private UserService userService;

    @Test
    public void testTranscation(){
        userService.testTransaction();
    }

}

[Note]: In order to successfully inject here, we need to turn on the Spring automatic scanning package and turn the entity class of UserServiceImpl into a Bean and register it in the Spring container.

Results of the:

Obviously a division by 0 exception occurred. Now let's look at the data in the database:

It can be seen that the operation before the exception is executed, and the operation after the exception is not. This business method is not managed by transactions, because the atomicity of things is not satisfied, which requires us to add transactions manually.

Spring supports programmatic transactions and declarative transactions:

Programmatic transaction: Remember that we manually commit or rollback in Mybatis, and directly control the submission and rollback of things by embedding code. This is a programmatic transaction.

Declarative transactions: Programmatic transactions require us to embed code for every method that requires things to be transformed, but this is a lot of and repetitive work; we have learned AOP before, and declarative transactions are embedded in transaction management through AOP. Code.

1. Import constraint tx

xmlns:tx="http://www.springframework.org/schema/tx"

http://http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd

2. Transaction Manager

Whether using programmatic or declarative, it must be done through the transaction manager, which encapsulates a set of technology-independent methods.

A. JDBC transaction

1) Register as Bean

    <bean id="transcationManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

2) Open the transaction manager with annotations

<tx:annotation-driven transaction-manager="transcationManager"/>

3) Use the @Transactional annotation to turn the method into a transaction

    @Transactional
    public void testTransaction() {

        int i = userDao.addUser(new User(3,"zzt","zjm"));
        System.out.println(i);

        int j = 1 / 0;

        userDao.updateUserById(new User(3,"withstand","pain"));

    }

4) Test

At this point, the entire business method becomes a transaction.

As we have learned before, the addition, deletion and modification operations involved in the mapper constructed by SqlSession will only be updated to the database when submitted, and SqlSessionTemplate actually helps us commit or roll back the addition, deletion and modification of a single mapper, but the example is involved The two operations are merged into one business method, so we must transform the method itself into a transaction.

B. The configuration file enables declarative transactions

    <bean id="transcationManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transcationManager">
        <tx:attributes>
            <!--配置哪些方法用什么样的事务,配置事物的传播特性-->
            <tx:method name="add*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="search*" propagation="REQUIRED"/>
            <!--查询无需事务 设置只读-->
            <tx:method name="get*" read-only="true"/>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!--用AOP织入事务-->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.zt.Service.Impl.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>

Remove the configuration of the transaction annotation mode in the configuration file, and remove the @Transactional on the method. After the test, the transaction can be seen successfully.

Detailed explanation of transaction propagation characteristics:

Transaction propagation behavior is how transactions are propagated among these methods when multiple transaction methods call each other. Spring supports 7 transaction propagation behaviors:

Transaction propagation behavior type Description
PROPAGATION_REQUIRED If there is no transaction currently, create a new transaction, if there is already a transaction, join it. This is the most common choice.
PROPAGATION_SUPPORTS Support the current transaction, if there is no transaction currently, it is executed in a non-transactional manner.
PROPAGATION_MANDATORY Use the current transaction, and throw an exception if there is no current transaction.
PROPAGATION_REQUIRES_NEW Create a new transaction. If a transaction currently exists, suspend the current transaction.
PROPAGATION_NOT_SUPPORTED The operation is performed in a non-transactional manner. If there is a transaction currently, the current transaction is suspended.
PROPAGATION_NEVER Execute in a non-transactional manner. If there is a transaction currently, an exception is thrown.
PROPAGATION_NESTED If a transaction currently exists, it is executed within a nested transaction. If there is no transaction currently, perform an operation similar to PROPAGATION_REQUIRED.

Spring's default transaction propagation method is REQUIRED, which is suitable for most situations.

Guess you like

Origin blog.csdn.net/qq_39304630/article/details/112587261