Spring transaction management

Posted by djsl on Tue, 08 Mar 2022 10:00:31 +0100

1. What is a business?

In a series of operations on the database, ensure that they succeed or fail at the same time, and there can be no partial success or partial failure. This series of operations is called database transactions.

2. Characteristics of transactions

Atomicity: refers to that a transaction is an inseparable work unit, and the operations of the transaction either occur or do not occur.

Consistency: the integrity of data before and after the transaction must be consistent.

Isolation: when multiple users access the database concurrently, the transactions of one user cannot be disturbed by the transactions of other users, and the data of multiple concurrent users are isolated from each other.

Persistence: once a transaction is committed, its changes to the data in the database are permanent. Then, even if the database fails, it should not have any impact on it.

3. Isolation level of transactions

When using java operation, set the isolation level from high to low as follows:

Serializable: it can avoid dirty reading, non repeatable reading and virtual reading.

Repeatable read: it can avoid dirty reading and non repeatable reading. (can be read repeatedly)

Read committed: to avoid dirty reading. (read submitted).

Read uncommitted: the lowest level. The above conditions are not guaranteed (read uncommitted).

Dirty read: refers to that one transaction reads uncommitted data from another transaction.

Non repeatable reading: read a row of data in a table within a transaction, and the reading results are different multiple times (one transaction reads the data submitted by another transaction).

Virtual read: refers to the data inserted by other transactions read in one transaction, resulting in inconsistent data.

Note: the default transaction level of most databases is Read committed, such as SqlServer Oracle. The default isolation level of MySQL is Repeatable read.

4. Transaction control manager of spring

Transaction provided by Spring: platform transaction manager, which provides three methods

getTransaction(TransactionDefinition) -- get a transaction management object

Transaction definition: transaction descriptor [simply set the transaction to be operated]

commit() commit transaction

rollback() transaction rollback

According to the different frameworks used by dao layer (persistence layer / data access layer), the main implementation classes of PlatformTransactionManager are roughly as follows:

1. When JDBC and MyBatis are used for data persistence: DataSourceTransactionManager class
 2. When Hibernate is used for data persistence: HibernateTransactionManager class

5. Specific transaction management operations [declarative transaction management]

Declarative transaction management -- without writing java code, set transaction management through configuration in Spring configuration file.

1). Transaction management operation based on xml

(1) Download dependent packages

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.1.5.RELEASE</version>
    </dependency>
    <!-- spring-jdbc -->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.1.5.RELEASE</version>
    </dependency>
    <!-- spring_tx -->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.1.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.1.5.RELEASE</version>
    </dependency>
    <!-- MyBatis rely on -->
    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.6</version>
    </dependency>
    <!-- mybatis-spring Integration package -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.1</version>
    </dependency>
    <!-- mysql Database driven -->
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.38</version>
    </dependency>
    <!--druid Ali's connection pool-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.7</version>
    </dependency>

(2). Create mapper interface

import java.util.HashMap;

public interface TransferMapper {
    //Add money
    public void addMony(HashMap<String,Object> parms);
    //Reduce money
    public void lessMony(HashMap<String,Object> parms);

}

(3) Configuration mapping file

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wangxing.demo1.mapper.TransferMapper">
    <update id="addMoney" parameterType="java.util.HashMap">
        update t_account set money=money+#{mymoney} where user_name=#{myname};
    </update>
    <update id="lessMoney" parameterType="java.util.HashMap">
        update t_account set money=money-#{mymoney} where user_name=#{myname};
    </update>
</mapper>

(4) Writing Spring configuration files

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
        <!-- Configure automatic scanning package -->
        <context:component-scan base-package="com.demo.service"></context:component-scan>
        <!--Read resource file-->
        <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
        <!-- Configure data source -->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="${mydriver}"></property>
            <property name="url" value="${myurl}"></property>
            <property name="username" value="${myusername}"></property>
            <property name="password" value="${mypassword}"></property>
        </bean>
        <bean class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"></property>
            <property name="mapperLocations" value="classpath:TransferMapper.xml"></property>
        </bean>
        <!-- Configure the scanning database access interface and create database access objects -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.demo.mapper"></property>
        </bean>
        <!--Transaction configuration-->
        <!-- Transaction configuration-->
        <!-- 1.Create transaction object-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!-- Configure data source -->
            <property name="dataSource" ref="dataSource"></property>
        </bean>
        <!-- 2 Create transaction -->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="transfer"/>
            </tx:attributes>
        </tx:advice>
        <!-- adopt aop Apply the above created things to the specified business methods -->
        <aop:config>
            <aop:pointcut id="point" expression="execution(* com.demo.service.TransferService.transfer())"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="point"></aop:advisor>

        </aop:config>
</beans>

(5) Create business processing class

import com.demo.mapper.TransferMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
@Service
public class TransferService {
    @Autowired
    private TransferMapper transferMapper;
    public void transfer(){
        HashMap<String, Object> liuneng;
        liuneng = new HashMap<String, Object>();
        liuneng.put("name", "Zhang San");
        liuneng.put("age", 100);
        int i = 1/0;
        transferMapper.addMony(liuneng);
        HashMap<String, Object> zhaosi = new HashMap<String, Object>();
        zhaosi.put("name", "Li Si");
        zhaosi.put("age", 100);
        transferMapper.lessMony(zhaosi);
        System.out.println("Transaction added successfully");
    }
}

(6) configuration database link resource file

mydriver = com.mysql.jdbc.Driver
myurl = jdbc:mysql://127.0.0.1:3306/test
myusername = root
mypassword = 123456

(7) Testing

import com.demo.service.TransferService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestMain {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContextTwo.xml");
        TransferService transferService = ac.getBean("transferService", TransferService.class);
        transferService.transfer();
    }
}

 2). Annotation based transaction management operations

The steps are the same as above and need to be changed (4) and (5)

(4) Spring configuration file

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
       <context:component-scan base-package="com.demo.service"></context:component-scan>
       <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="${mydriver}"></property>
            <property name="url" value="${myurl}"></property>
            <property name="username" value="${myusername}"></property>
            <property name="password" value="${mypassword}"></property>
        </bean>
        <bean class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"></property>
            <property name="mapperLocations" value="classpath:TransferMapper.xml"></property>
        </bean>
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.demo.mapper"></property>
        </bean>
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
        <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>

(5) Add annotation to Service

import com.demo.mapper.TransferMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
@Service
public class TransferService {
    @Autowired
    private TransferMapper transferMapper;
    @Transactional
    public void transfer(){
        HashMap<String, Object> liuneng;
        liuneng = new HashMap<String, Object>();
        liuneng.put("name", "Zhang San");
        liuneng.put("age", 100);
        int i = 1/0;
        transferMapper.addMony(liuneng);
        HashMap<String, Object> zhaosi = new HashMap<String, Object>();
        zhaosi.put("name", "Li Si");
        zhaosi.put("age", 100);
        transferMapper.lessMony(zhaosi);
        System.out.println("Transaction added successfully");
    }
}

Helpless from not strong enough

 

Topics: Java Spring Back-end