Spring framework transaction processing

Posted by Awesome Trinity on Wed, 02 Mar 2022 16:50:26 +0100

What is a transaction

1. What is a transaction

Transaction refers to a set of sql statements, in which there are multiple sql statements
It may be insert, update, select or delete. We hope that these multiple sql statements can succeed or fail. The execution of these sql statements is consistent and executed as a whole.

2. When do you think of using transactions

When my operation involves getting multiple tables or insert ing, updating and deleting multiple sql statements. You need to ensure that these statements are successful to complete my function, or fail to ensure that the operation meets the requirements.

3. What kind of transaction is required by your business method, and describe the type of transaction required.

Describe the transactions required by the method:

Isolation level of transaction:

There are four values. (packaging safety in case of high concurrency)
These constants are based on ISOLATION_ start. Isometric ISOLATION_XXX.

  • DEFAULT: the DEFAULT transaction isolation level of DB is adopted. MySql defaults to REPEATABLE_READ; Oracle defaults to READ_COMMITTED.
  • READ_UNCOMMITTED: read uncommitted. No concurrency issues were resolved.
  • READ_COMMITTED: read committed. Solve dirty reading, there are non repeatable reading and unreal reading.
  • REPEATABLE_READ: repeatable. Solve dirty reading, non repeatable reading and phantom reading
  • SERIALIZABLE: serialization. There is no concurrency problem.
Timeout of transaction

Indicates the longest execution time of a method. If the execution time of the method exceeds the time, the transaction will be rolled back.
The unit is seconds, integer value, and the default is - 1

Propagation behavior of transactions

Control whether business methods have transactions and what kind of transactions they have.
7 propagation behaviors, indicating that when your business method is called, the transaction is used between methods.

  • PROPAGATION_REQUIRED
    The specified method must be executed within a transaction. If there is a current transaction, it will be added to the current transaction; If nothing happens at present
    Create a new transaction. This propagation behavior is the most common choice and the default transaction propagation behavior of Spring.
    If the propagation behavior is added to the doOther() method. If the doSome() method is calling the doOther() method, it is doing something
    If it runs in the transaction, the execution of the doOther() method is also added to the transaction for execution. If the doSome() method is called
    If the doOther() method is not executed within a transaction, the doOther() method creates a transaction and executes it.

  • PROPAGATION_REQUIRES_NEW
    The specified method supports the current transaction, but if there is no current transaction, it can also be executed in a non transactional manner.

  • PROPAGATION_SUPPORTS
    Always create a new transaction. If there is a current transaction, suspend the current transaction until the new transaction is executed.

The above three need to be mastered

  • PROPAGATION_MANDATORY
  • PROPAGATION_NESTED
  • PROPAGATION_NEVER
  • PROPAGATION_NOT_SUPPORTED
4. The time when the transaction is committed and rolled back
  • When your business method is executed successfully, no exception is thrown. When the method is executed, spring commits the transaction after the method is executed. Transaction manager commit
  • When your business method throws a runtime exception or ERROR, spring executes rollback and calls the rollback of the transaction manager
    Definition of runtime exception: RuntimeException and its subclasses are runtime exceptions, such as nullpointexception and numberformatexception
  • When your business method throws a non runtime exception, mainly the checked exception, commit the transaction
    Checked exception: an exception that must be handled in your code. For example, IOException, SQLException

Using transaction processing steps in Spring

give an example:

Buy goods trans_sale project
This example is to purchase goods, simulate users to place orders, add sales records to the order table, and reduce inventory from the commodity table.

Implementation steps:

Step0: create database table

Create two database tables, sale and goods
1. Sales table

create table sale(id int(11) not null AUTO_INCREMENT, gid int(11) not null, nums int(11), primary key (id));


2. goods list

create table goods(id int(11) not null, name varchar(100), amount int(11), price float(0), primary key(id));


goods table data

Step 1: Maven relies on POM xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.changsha</groupId>
  <artifactId>springtrans</artifactId>
  <version>1.0-SNAPSHOT</version>


  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <!--Unit test dependency-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!--aspectj rely on-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
    <!--Spring rely on-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
    <!--mybatis rely on-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.24</version>
    </dependency>
    <!--Connection pool dependency-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.12</version>
    </dependency>



  </dependencies>

  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory><!--Directory of-->
        <includes><!--Including the.properties,.xml The files will be scanned-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>


</project>

Step 2: create entity class

Used to store the data of a row in the database table
The goods class holds a row of data in the goods table

package com.changsha.domain;

public class Goods {
    private Integer id;
    private String name;
    private Integer amount;
    private Float price;
    
    public Goods() {

    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAmount() {
        return amount;
    }

    public void setAmount(Integer amount) {
        this.amount = amount;
    }

    public Float getPrice() {
        return price;
    }

    public void setPrice(Float price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Goods{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", amount=" + amount +
                ", price=" + price +
                '}';
    }
}

One row of data in sale table

package com.changsha.domain;

public class Sale {
    private Integer id;
    private Integer gid;
    private Integer nums;

    public Sale(Integer id, Integer gid, Integer nums) {
        this.id = id;
        this.gid = gid;
        this.nums = nums;
    }

    public Sale() {

    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getGid() {
        return gid;
    }

    public void setGid(Integer gid) {
        this.gid = gid;
    }

    public Integer getNums() {
        return nums;
    }

    public void setNums(Integer nums) {
        this.nums = nums;
    }

    @Override
    public String toString() {
        return "Sale{" +
                "id=" + id +
                ", gid=" + gid +
                ", nums=" + nums +
                '}';
    }
}

Step 3: define dao interface

Define the interfaces of two Daos, sale dao and goodsdao
dao interface, which defines the operation on the database

package com.changsha.dao;

import com.changsha.domain.Goods;
import org.apache.ibatis.annotations.Param;

public interface GoodsDao {
    //Update inventory
    //Goods refers to the information of the goods purchased by the user this time
    int updateGoods(Goods goods);

    //Query commodity information

    Goods selectGoods(@Param("gid") Integer id);
}

dao of sale

package com.changsha.dao;

import com.changsha.domain.Sale;

public interface SaleDao {
    //Add sales record
    int insertSale(Sale sale);
}

Step 4: define the sql mapping file corresponding to dao interface

mapper configuration file (need to have the same name and directory as dao interface)
GoodsDao.xml

<?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">
<!--
 namespace: Must have a value, a unique custom string
 Recommended: dao Fully qualified name of the interface
 Declarative id The suggestion is the same as the name of the interface method
-->
<mapper namespace="com.changsha.dao.GoodsDao">

    <update id="updateGoods">
      update goods set amount = amount - #{amount} where id = #{id}
    </update>

    <select id="selectGoods" resultType="com.changsha.domain.Goods">
        select * from goods where id = #{gid}
    </select>

</mapper>

SaleDao.xml

<?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">
<!--
 namespace: Must have a value, a unique custom string
 Recommended: dao Fully qualified name of the interface
 Declarative id The suggestion is the same as the name of the interface method
-->
<mapper namespace="com.changsha.dao.SaleDao">

    <insert id="insertSale">
      insert into sale(gid,nums) values (#{gid},#{nums})
    </insert>

</mapper>
Define exception class (not required)

Define the exception class NotEnoughException that may be thrown by the service layer

package com.changsha.excep;


//Custom runtime exception
public class NotEnoughException extends RuntimeException{
    public NotEnoughException() {
        super();
    }

    public NotEnoughException(String message) {
        super(message);
    }
}

Step 5: create mybatis master configuration file

Because other connection pools are used, the database information does not need to be specified in this file

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <!--settings: control mybatis Global behavior-->
    <settings>
        <!--set up mybatis Output log-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <!--Alias settings-->
    <typeAliases>
        <!--name:Package name of entity class
            express com.bjpowernode.domain The column names in the package are aliases
            You can use Student express com.bjpowenrode.domain.Student
        -->
        <package name="com.changsha.domain"/>
    </typeAliases>


    <!-- sql mapper(sql Mapping file)Location of-->
    <mappers>
        <!--
          name: Is the name of the package. All the files in this package mapper.xml It can be loaded at one time
        -->
        <package name="com.changsha.dao"/>
    </mappers>
</configuration>

Step 6: define Service interface

Define the Service interface BuyGoodsService

package com.changsha.service;

public interface BuyGoodsService {
    //The method of purchasing goods. goodsId is the number of the purchased goods, and num is the quantity of the goods
    public  void buy(Integer goodsId, Integer nums);
}

Step 7: define the implementation class of the service

Defines the implementation class BuyGoodsServiceImpl of the service layer interface

package com.changsha.service.Impl;

import com.changsha.dao.GoodsDao;
import com.changsha.dao.SaleDao;
import com.changsha.domain.Goods;
import com.changsha.domain.Sale;
import com.changsha.excep.NotEnoughException;
import com.changsha.service.BuyGoodsService;

public class BuyGoodsServiceImpl implements BuyGoodsService {

    private SaleDao saleDao;
    private GoodsDao goodsDao;

    @Override
    public void buy(Integer goodsId, Integer nums) {
        System.out.println("=======buy Start of method=======");
        //Record sales information and add records to the sale table
        Sale sale = new Sale();
        sale.setGid(goodsId);
        sale.setNums(nums);
        saleDao.insertSale(sale);

        //Update inventory
        Goods goods = goodsDao.selectGoods(goodsId);
        if(goods == null){
            //Item does not exist
            throw new NullPointerException("The number is" + goodsId+"Item does not exist");
        } else if(goods.getAmount() < nums){
            //Insufficient inventory of goods
            throw new NotEnoughException("The number is" + goodsId+"Insufficient inventory of goods");
        }

        //If there are no exceptions above, you can modify the inventory
        Goods buyGoods = new Goods();
        buyGoods.setId(goodsId);
        buyGoods.setAmount(nums);
        goodsDao.updateGoods(buyGoods);
        System.out.println("=======buy Method completion=======");
    }

    public void setSaleDao(SaleDao saleDao) {
        this.saleDao = saleDao;
    }

    public void setGoodsDao(GoodsDao goodsDao) {
        this.goodsDao = goodsDao;
    }

}

Step 8: create Spring configuration file content

1. Steps for using @ Transactional (applicable to small and medium-sized projects):

1). The transaction manager object needs to be declared
    <!--Claim transaction manager-->
    <bean id="tansactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="myDataSource"/>

    </bean>
2). Turn on the transaction annotation driver and tell the spring framework that I want to use annotation to manage transactions.

spring uses the aop mechanism to create the proxy object of the class where @ Transactional is located, and adds the transaction function to the method.
spring adds transactions to business methods:
Before the execution of your business method, start the transaction first, commit or roll back the transaction after the business method, and use aop surround notification

@Around("The business method name of the transaction function you want to add")
		 Object myAround(){
           Start the transaction, spring Open it for you
			  try{
			     buy(1001,10);
				  spring Transaction manager for.commit();
			  }catch(Exception e){
             spring Transaction manager for.rollback();
			  }
			 
		 }

Turn on spring settings for transactions
The annotation driven package must end with tx

    <!--2. Turn on the transaction annotation driver and tell spring Use annotations to manage transactions and create proxy objects
       transaction-manager:Of the transaction manager object id-->
    <tx:annotation-dridven transaction-manager="tansactionManager"/>
3). Add the @ transactional annotation to the method you need to do the transaction


The code is as follows

package com.changsha.service.Impl;

import com.changsha.dao.GoodsDao;
import com.changsha.dao.SaleDao;
import com.changsha.domain.Goods;
import com.changsha.domain.Sale;
import com.changsha.excep.NotEnoughException;
import com.changsha.service.BuyGoodsService;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

public class BuyGoodsServiceImpl implements BuyGoodsService {

    private SaleDao saleDao;
    private GoodsDao goodsDao;

    @Transactional(
            propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            readOnly = false,
            rollbackFor = {
                    NullPointerException.class,
                    NotEnoughException.class
            }
    )
    @Override
    public void buy(Integer goodsId, Integer nums) {
        System.out.println("=======buy Start of method=======");
        //Record sales information and add records to the sale table
        Sale sale = new Sale();
        sale.setGid(goodsId);
        sale.setNums(nums);
        saleDao.insertSale(sale);

        //Update inventory
        Goods goods = goodsDao.selectGoods(goodsId);
        if(goods == null){
            //Item does not exist
            throw new NullPointerException("The number is" + goodsId+"Item does not exist");
        } else if(goods.getAmount() < nums){
            //Insufficient inventory of goods
            throw new NotEnoughException("The number is" + goodsId+"Insufficient inventory of goods");
        }

        //If there are no exceptions above, you can modify the inventory
        Goods buyGoods = new Goods();
        buyGoods.setId(goodsId);
        buyGoods.setAmount(nums);
        goodsDao.updateGoods(buyGoods);
        System.out.println("=======buy Method completion=======");
    }

    public void setSaleDao(SaleDao saleDao) {
        this.saleDao = saleDao;
    }

    public void setGoodsDao(GoodsDao goodsDao) {
        this.goodsDao = goodsDao;
    }

}

Since annotations are the default values used in most cases, the assignment can be omitted directly

package com.changsha.service.Impl;

import com.changsha.dao.GoodsDao;
import com.changsha.dao.SaleDao;
import com.changsha.domain.Goods;
import com.changsha.domain.Sale;
import com.changsha.excep.NotEnoughException;
import com.changsha.service.BuyGoodsService;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

public class BuyGoodsServiceImpl implements BuyGoodsService {

    private SaleDao saleDao;
    private GoodsDao goodsDao;

    @Transactional
    @Override
    public void buy(Integer goodsId, Integer nums) {
        System.out.println("=======buy Start of method=======");
        //Record sales information and add records to the sale table
        Sale sale = new Sale();
        sale.setGid(goodsId);
        sale.setNums(nums);
        saleDao.insertSale(sale);

        //Update inventory
        Goods goods = goodsDao.selectGoods(goodsId);
        if(goods == null){
            //Item does not exist
            throw new NullPointerException("The number is" + goodsId+"Item does not exist");
        } else if(goods.getAmount() < nums){
            //Insufficient inventory of goods
            throw new NotEnoughException("The number is" + goodsId+"Insufficient inventory of goods");
        }

        //If there are no exceptions above, you can modify the inventory
        Goods buyGoods = new Goods();
        buyGoods.setId(goodsId);
        buyGoods.setAmount(nums);
        goodsDao.updateGoods(buyGoods);
        System.out.println("=======buy Method completion=======");
    }

    public void setSaleDao(SaleDao saleDao) {
        this.saleDao = saleDao;
    }

    public void setGoodsDao(GoodsDao goodsDao) {
        this.goodsDao = goodsDao;
    }

}

Annotate the full spring configuration file for how transactions are handled

<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">


    <!--
       Write the configuration information of the database in an independent file, compile and modify the configuration content of the database
       spring know jdbc.properties File location
    -->
    <context:property-placeholder location="classpath:jdbc.properties" />

    <!--Declare data source DataSource,The function is to connect to the database-->
    <bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource"
          init-method="init" destroy-method="close">
        <!--set Inject into DruidDataSource Provide database information-->
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxActive" value="${jdbc.maxActive}"/>
    </bean>



    <!--The statement is mybatis Provided in SqlSessionFactoryBean Class, which is created internally SqlSessionFactory of
        SqlSessionFactory  sqlSessionFactory = new ..
    -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--set Injection, paying the database connection pool dataSource attribute-->
        <property name="dataSource" ref="myDataSource"/>
        <!--mybatis Location of the master profile
           configLocation Attribute is Resource Type, read configuration file
           Its assignment, using value,Specify the path of the file, using classpath:Indicates the location of the file
        -->
        <property name="configLocation" value="springtrans.xml"/>

    </bean>



    <!--establish dao Objects, using SqlSession of getMapper(StudentDao.class)
        MapperScannerConfigurer:Call internally getMapper()Generate each dao Proxy object for the interface.-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--appoint SqlSessionFactory Object id-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!--Specify the package name, which is dao The package name of the interface.
            MapperScannerConfigurer It will scan all interfaces in the package and execute each interface
            once getMapper()Method to get the of each interface dao Object.
            Created dao Object into spring In the container. dao The default name of an object is the initial lowercase of the interface name
        -->
        <property name="basePackage" value="com.changsha.dao"/>
    </bean>



    <!--statement service-->
    <bean id="buyService" class="com.changsha.service.Impl.BuyGoodsServiceImpl">
        <property name="goodsDao" ref="goodsDao"/>
        <property name="saleDao" ref="saleDao"/>
    </bean>


    <!--Claim transaction manager-->
    <bean id="tansactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="myDataSource"/>

    </bean>


    <!--2. Turn on the transaction annotation driver and tell spring Use annotations to manage transactions and create proxy objects
       transaction-manager:Of the transaction manager object id-->
    <tx:annotation-driven transaction-manager="tansactionManager"/>

</beans>


2. Use aspectj framework (for large projects)

1) maven relies on POM xml

Dependency coordinates of newly added aspectj

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-aspects</artifactId>
	<version>5.2.5.RELEASE</version>
</dependency>
2) Add a transaction manager to the container
    <!--Claim transaction manager-->
    <bean id="tansactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="myDataSource"/>
    </bean>
3) Configure transaction notifications

Set relevant properties for transaction notification. Used to specify how transactions are woven into which methods.
For example, the transaction requirements applied to the buy method are necessary, and the business should be rolled back when an exception occurs in the buy method.

    <!--2.Declare the transaction attributes of the business method (isolation level, propagation behavior, timeout)
          id:Custom name, indicating <tx:advice> and </tx:advice>Configuration content between
          transaction-manager:Of the transaction manager object id
    -->
    <tx:advice id="myAdvice" transaction-manager="transactionManager">
        <!--tx:attributes: Configure transaction properties-->
        <tx:attributes>
            <!--tx:method: Configure transaction attributes for specific methods, method There can be multiple methods, and the transaction attributes can be set for different methods
                name:Method name, 1) complete method name without package and class.
                              2)Method can use wildcards,* Represents any character
                propagation: Propagation behavior, enumeration value
                isolation: Isolation level
                rollback-for: The exception class name you specified, fully qualified class name. If an exception occurs, it must be rolled back
            -->
            <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT"
                       rollback-for="java.lang.NullPointerException,com.bjpowernode.excep.NotEnoughException"/>

            <!--Use wildcards to specify many methods-->
            <tx:method name="add*" propagation="REQUIRES_NEW" />
            <!--Specify modification method-->
            <tx:method name="modify*" />
            <!--Delete method-->
            <tx:method name="remove*" />
            <!--Query method, query,search,find-->
            <tx:method name="*" propagation="SUPPORTS" read-only="true" />
        </tx:attributes>
    </tx:advice>

In the method tag, first find the transaction method with precise range (specify method name), then find the semi universal method, and finally*

4) Configuration enhancer

Specify to whom the configured transaction notification will be woven.

    <!--to configure aop-->
    <aop:config>
        <!--Configure pointcut expression: specify which classes in the package and which transactions to use
            id:The name and unique value of the pointcut expression
            expression: Pointcut expressions that specify which classes use transactions, aspectj The proxy object is created

            com.bjpowernode.service
            com.crm.service
            com.service
        -->
        <aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))"/>

        <!--Configuring enhancers: associations adivce and pointcut
           advice-ref:Notice, above tx:advice Where is the configuration
           pointcut-ref: Of pointcut expressions id
        -->
        <aop:advisor advice-ref="myAdvice" pointcut-ref="servicePt" />
    </aop:config>

Pointcut expression in aspectj framework It is introduced in

Complete spring configuration file for transaction processing through aspectj framework

<?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 https://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 https://www.springframework.org/schema/aop/spring-aop.xsd">


    <!--
       Write the configuration information of the database in an independent file, compile and modify the configuration content of the database
       spring know jdbc.properties File location
    -->
    <context:property-placeholder location="classpath:jdbc.properties" />

    <!--Declare data source DataSource,The function is to connect to the database-->
    <bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource"
          init-method="init" destroy-method="close">
        <!--set Inject into DruidDataSource Provide database information-->
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxActive" value="${jdbc.maxActive}"/>
    </bean>



    <!--The statement is mybatis Provided in SqlSessionFactoryBean Class, which is created internally SqlSessionFactory of
        SqlSessionFactory  sqlSessionFactory = new ..
    -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--set Injection, paying the database connection pool dataSource attribute-->
        <property name="dataSource" ref="myDataSource"/>
        <!--mybatis Location of the master profile
           configLocation Attribute is Resource Type, read configuration file
           Its assignment, using value,Specify the path of the file, using classpath:Indicates the location of the file
        -->
        <property name="configLocation" value="springtrans.xml"/>

    </bean>



    <!--establish dao Objects, using SqlSession of getMapper(StudentDao.class)
        MapperScannerConfigurer:Call internally getMapper()Generate each dao Proxy object for the interface.-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--appoint SqlSessionFactory Object id-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!--Specify the package name, which is dao The name of the package where the interface is located.
            MapperScannerConfigurer It will scan all interfaces in the package and execute each interface
            once getMapper()Method to get the of each interface dao Object.
            Created dao Object into spring In the container. dao The default name of an object is the initial lowercase of the interface name
        -->
        <property name="basePackage" value="com.changsha.dao"/>
    </bean>



    <!--statement service-->
    <bean id="buyService" class="com.changsha.service.Impl.BuyGoodsServiceImpl">
        <property name="goodsDao" ref="goodsDao"/>
        <property name="saleDao" ref="saleDao"/>
    </bean>


    <!--Claim transaction manager-->
    <bean id="tansactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="myDataSource"/>
    </bean>


    <!--2.Declare the transaction attributes of the business method (isolation level, propagation behavior, timeout)
          id:Custom name, indicating <tx:advice> and </tx:advice>Configuration content between
          transaction-manager:Of the transaction manager object id
    -->

    <!--Imported advice Is the package name tx ending-->
    <tx:advice id="myAdvice" transaction-manager="tansactionManager">
        <!--tx:attributes: Configure transaction properties-->
        <tx:attributes>
            <!--tx:method: Configure transaction attributes for specific methods, method There can be multiple methods, and the transaction attributes can be set for different methods
                name:Method name, 1) complete method name without package and class.
                              2)Wildcard methods can be used,* Represents any character
                propagation: Propagation behavior, enumeration value
                isolation: Isolation level
                rollback-for: The exception class name you specified, fully qualified class name. If an exception occurs, it must be rolled back
            -->
            <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT"
                       rollback-for="java.lang.NullPointerException,com.bjpowernode.excep.NotEnoughException"/>

            <!--Use wildcards to specify many methods-->
            <tx:method name="add*" propagation="REQUIRES_NEW" />
            <!--Specify modification method-->
            <tx:method name="modify*" />
            <!--Delete method-->
            <tx:method name="remove*" />
            <!--Query method, query,search,find-->
            <tx:method name="*" propagation="SUPPORTS" read-only="true" />
        </tx:attributes>
    </tx:advice>



    <!--Note the imported aop Is it correct-->
    <aop:config>
        <aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))"/>
        <aop:advisor advice-ref="myAdvice" pointcut-ref="servicePt" />
    </aop:config>

</beans>

Step 9: method test

package com.changsha;

import com.changsha.service.BuyGoodsService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Mytest {
    @Test
    public void test(){
        String config = "applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        BuyGoodsService buyGoodsService = (BuyGoodsService) ctx.getBean("buyService");
        //Becomes the object of a dynamic proxy
        System.out.println(buyGoodsService.getClass().getName());
        buyGoodsService.buy(1001,10);
    }
}

Topics: Java Database MySQL Mybatis Spring