Spring learning summary (12): transaction management in Spring

        At the end of the previous article, we brought up the problem, let's take a look at how to solve this kind of problem in Spring.

One, the introduction of transaction attributes in Spring

       The properties of transactions in Spring are as follows:

(1) Transaction propagation behavior (propagation)

When a transaction method is called by another transaction method, you must specify how the transaction should be propagated. For example: the method may continue to run in an existing transaction, or it may start a new transaction and run in its own transaction. Spring defines seven propagation behaviors, as shown in the following table:

Dissemination behavior value description
PROPAGATION_REQUIRED required Indicates that the current method must be run in a transaction. If the current transaction exists, the method will run in that transaction. Otherwise, start a new transaction
PROPAGATION_SUPPORTS supports Indicates that the current method does not require a transaction context, but if there is a current transaction, then the method will run in this transaction.
PROPAGATION_MANDATORY mandatory Indicates that the method must be run in a transaction. If the current transaction does not exist, an exception is thrown.
PROPAGATION_REQUIRED_NEW required_new Indicates that the current method must run in its own transaction. A new transaction will be started. If there is a current transaction, the original transaction is suspended during the execution of this method. If you use JATransactionManager, you need to access TransactionManager
PROPAGATION_NOT_SUPPORTED not_supported Indicates that the method should not be run in a transaction. If there is a current transaction, the original transaction is suspended during the execution of this method. If you use JATransactionManager, you need to access TransactionManager
PROPAGATION_NEVER never Indicates that the current method should not be run in the context of a transaction. If a transaction is currently running, an exception is thrown
PROPAGATION_NESTED nested Indicates that if there is already a transaction, then the method will run in a nested transaction. Nested transactions can be submitted or rolled back independently of the current transaction. If the current transaction does not exist, its behavior is the same as PROPAGATION_REQUIRED

(2) Transaction isolation level (isolation)

The five transaction isolation levels in Spring:
DEFAULT: Use the default isolation level of the back-end database (selection in spring)
READ_UNCOMMITED: Allow you to read the changed data that has not yet been committed. May cause dirty, phantom, and non-repeatable reads.
READ_COMMITTED: Allow reading after the concurrent transaction has been committed. Dirty reads can be prevented, but reads and non-repeatable reads can still occur.
REPEATABLE_READ: Multiple reads of the same field are consistent unless the data is changed by the transaction itself. Can prevent dirty, non-repeatable reads, but phantom reads may still occur.
SERIALIZABLE: Fully obey the ACID isolation level to ensure that no dirty, phantom, or non-repeatable reads occur. This is the slowest of all isolation levels, and it is typically done by completely locking the data tables involved in the transaction.

(3) Timeout

The transaction needs to be committed within a certain period of time, if not committed, it will be rolled back. The default value is -1, and the setting time is in seconds.

(4) Whether it is read-only (readOnly)

The default value is false, which means that you can query, modify, delete, add and other operations. Reading refers to query operations, and writing refers to adding, modifying, and deleting operations.

(5) Rollback (rollbackFor)

Set which abnormal transactions are rolled back.

(6) No rollback (noRollbackFor)

Set which abnormal transactions are not rolled back.

Two, programmatic transaction management

       Programmatic transactions refer to the implementation of transactions through coding, which is similar to JDBC programming to achieve transaction management. Manage the use of TransactionTemplate or directly use the underlying PlatformTransactionManager. For programmatic transaction management, Spring recommends TransactionTemplate.

(1) Configure transactionTemplate and transaction manager in bean.xml

    <!--  配置transactionTemplate -->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"></property>
    </bean>

    <!--  创建事务管理器  -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

(2) In the tranferAccount() method, the logic is executed through transactionTemplate.execute, and the return value is passed to the execute() of the TransactionTemplate through the method in the TransactionCallback interface. The transaction rollback is achieved by calling the setRollbackOnly() method of TransactionStatus.

@Service
public class UserService {
    @Autowired
    private IUserDao userDao;
    @Autowired
    private TransactionTemplate transactionTemplate;
    public void tranferAccount(){
        transactionTemplate.execute(new TransactionCallback<String>() {

            @Override
            public String doInTransaction(TransactionStatus transactionStatus) {
                try{
                    userDao.reduceMoney();
                    int i = Integer.parseInt("123a");
                    userDao.addMoney();
                }catch (Exception e){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动开启事务回滚
                    transactionStatus.setRollbackOnly();
                    return null;
                }
                return null;
            }
        });

    }
}

Three, declarative transaction management

       Declarative transaction management is based on AOP. Its essence is to intercept before and after the method, and then create or add a transaction before the target method starts, and submit or roll back the transaction according to the execution after the target method is executed. The biggest advantage of declarative transactions is that there is no need to manage transactions through programming, so that there is no need to dope transaction management code in the business logic code. You only need to make relevant transaction rule declarations in the configuration file (or through @Transactional Annotation), you can apply transaction rules to business logic

1. XML-based declarative transaction management

<!--  创建事务管理器  -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 编写通知:对事务管理器进行增强(通知),编写切入点和具体执行事务的细节   -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--    给切入点方法添加事务详情        -->
            <tx:method name="tranferAccount" propagation="REQUIRED" isolation="READ_COMMITTED"/>
            <tx:method name="*" read-only="false"/>
        </tx:attributes>
    </tx:advice>
    <!--  Aop编写:让Spring自动对目标生成代理,需要使用 AspectJ表达式 -->
    <aop:config>
        <!--    切入点    -->
        <aop:pointcut id="pt" expression="execution(* com.yht.example8.service.UserService.*(..))"/>
        <!--   切面:将切入点和通知整合     -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>
    </aop:config>

2. Declarative transaction management based on annotations

(1) Open transaction annotations in bean.xml

    <!--  开启事务注解  -->
    <tx:annotation-driven></tx:annotation-driven>

(2) Modify the UserService class and add the annotation @Transactional

@Service
@Transactional
public class UserService {
    @Autowired
    private IUserDao userDao;
    @Autowired
    private TransactionTemplate transactionTemplate;
    public void tranferAccount(){
        userDao.reduceMoney();
        int i = Integer.parseInt("123a");
        userDao.addMoney();
    }
}

Description: Fully annotated way to achieve declarative transaction management, provide a MyAopConfig class under config, as follows:

@Configuration    //配置类
@ComponentScan("com.yht.example8")      //组件扫描
@EnableAspectJAutoProxy     //开启事务
public class MyAopConfig {
    // @Bean:用于把当前方法的返回值作为bean对象存入spring的ioc容器中

    /**
     * 获取数据库连接池
     * @return
     */
    @Bean
    public DruidDataSource getDruidDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }

    /**
     * 获取JdbcTemplate
     * @param dataSource 由IOC容器提供
     * @return
     */
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        //注入dataSource
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }
}

 

Guess you like

Origin blog.csdn.net/weixin_47382783/article/details/112861374