aop transaction in spring

affairs

Why use AOP transactions in Spring?

First, let's take an example to understand what is a transaction operation? and the problems that arise? The example used by the teacher in the course is an example of a transfer transaction. A transfers money to B. At this time, the service layer provides a method to perform subtraction operations in the database. After B receives the money, it will open a transaction for adding operations. However, if A has an exception in the process of making money to B, it is likely that the subtraction operation in A has been executed, but B has not received the money, then the money is gone at this time, then at this time We should provide a solution so that A will not perform the subtraction operation after an exception occurs, so that the above situation can be avoided. Through the learning of AOP, we can use SpringAOP to perform the functions of the addition and subtraction methods in the service layer. Step up and start learning!

characteristics of things

Atomicity, Consistency, Isolation, Durability

Transaction Concurrency Issues

Dirty reading, non-repeatable reading, phantom reading noun explanation: blog address

transaction isolation level

1 Read Uncommitted2
Read Committed4
Repeatable Read8
Serialization
Glossary

spring encapsulates transaction management code

transaction operation

  1. open transaction
  2. commit transaction
  3. rollback transaction

Before executing the SQL statement, first execute start transaction, which opens a transaction (the starting point of the transaction), then you can execute multiple SQL statements, and finally end the transaction, commit means commit, that is, the multiple SQL statements in the transaction are The effect made is persisted to the database. Or rollback, which means rollback, that is, rollback to the starting point of the transaction, and all previous operations have been undone!

transaction operation object

Because on different platforms, the code for operating transactions is different. Spring provides an interface

  1. DataSourceTransactionManager
  2. HibernateTransitionmanager
    Note: Play transaction management in spring. The core object is the TransactionManager object

Introduction to the properties of spring management transactions

  1. transaction isolation level
  2. Whether read-only: true read-only, false operable
  3. Transaction Propagation Behavior
    write picture description here

Spring manages transactions

Coded


1. Configure the core transaction manager to the spring container

<!-- 事物核心管理器 ,封装了所有的事物操作依赖于连接池-->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

2. Configure the TransactionTemplate template

<!-- 事务模板对象 -->
<bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
    <property name="transactionManager" ref="transactionManager"></property>
</bean>

3. Inject the transaction template into the Service

<!-- 3.Service-->
<bean name="accountService" class="cn.itcast.service.AccountServiceImpl" >
    <property name="ad" ref="accountDao" ></property>
    <property name="tt" ref="transactionTemplate" ></property>
</bean>  

4. Call the template in the Service

    public void transfer(final Integer from,final Integer to,final Double money) {

        tt.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus arg0) {
                //减钱
                ad.decreaseMoney(from, money);
                int i = 1/0;
                //加钱
                ad.increaseMoney(to, money);
            }
        });


    }

xml configuration (aop)

1. Import package:
write picture description here
2. Import new constraints (tx)
write picture description here

beans: the most basic
context: read properties configuration
aop: configure aop
tx: configure transaction notification

3. Configure Notifications

<!-- 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager" >
    <tx:attributes>
        <!-- 以方法为单位,指定方法应用什么事务属性
            isolation:隔离级别
            propagation:传播行为
            read-only:是否只读
         -->
        <tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
        <tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
        <tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
        <tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
        <tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
        <tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
        <tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
        <tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
        <tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
    </tx:attributes>
</tx:advice>

4. Configure weaving notifications into targets

<!-- 配置织入 -->
<aop:config  >
    <!-- 配置切点表达式 -->
    <aop:pointcut expression="execution(* cn.itcast.service.*ServiceImpl.*(..))" id="txPc"/>
    <!-- 配置切面 : 通知+切点
            advice-ref:通知的名称
            pointcut-ref:切点的名称
     -->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" />
</aop:config>

Annotation configuration

When annotating and configuring ApplicationContext.xml, you need to remove the configuration transaction notification and configuration weaving in the xml configuration injection in the above method,
and then add annotations to the service implementation class method.

The first way annotation is added on the method:

    @Override
    @Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
    public void transfer(final Integer from,final Integer to,final Double money) {
                //减钱
                ad.decreaseMoney(from, money);
                int i = 1/0;
                //加钱
                ad.increaseMoney(to, money);
    }

The first method is to add annotations to the class: in order to avoid the need to manually add annotations every time a method is rewritten, this method will inject each method uniformly. If you want to change the annotation content of a method, such as read-only The attribute is changed to be operable, and an annotation can be added to the method.

//统一配置
@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=true)
public class AccountServiceImpl implements AccountService {

    private AccountDao ad ;
    private TransactionTemplate tt;
    //只读属性改成可操作
    @Override
    @Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
    public void transfer(final Integer from,final Integer to,final Double money) {
                //减钱
                ad.decreaseMoney(from, money);
                int i = 1/0;
                //加钱
                ad.increaseMoney(to, money);
    }
}

Logical relationship diagram:
write picture description here

Exercise code:
xml configuration injection applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">

<!-- 指定spring读取db.properties配置 -->
<context:property-placeholder location="classpath:db.properties"  />

<!-- 事务核心管理器,封装了所有事务操作. 依赖于连接池 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
    <property name="dataSource" ref="dataSource" ></property>
</bean>
<!-- 事务模板对象 -->
<bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate" >
    <property name="transactionManager" ref="transactionManager" ></property>
</bean>

<!-- 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager" >
    <tx:attributes>
        <!-- 以方法为单位,指定方法应用什么事务属性
            isolation:隔离级别
            propagation:传播行为
            read-only:是否只读
         -->
        <tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
        <tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
        <tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
        <tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
        <tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
        <tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
        <tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
        <tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
        <tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
    </tx:attributes>
</tx:advice>


<!-- 配置织入 -->
<aop:config  >
    <!-- 配置切点表达式 -->
    <aop:pointcut expression="execution(* cn.itcast.service.*ServiceImpl.*(..))" id="txPc"/>
    <!-- 配置切面 : 通知+切点
            advice-ref:通知的名称
            pointcut-ref:切点的名称
     -->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" />
</aop:config>


<!-- 1.将连接池 -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
    <property name="jdbcUrl" value="${jdbc.jdbcUrl}" ></property>
    <property name="driverClass" value="${jdbc.driverClass}" ></property>
    <property name="user" value="${jdbc.user}" ></property>
    <property name="password" value="${jdbc.password}" ></property>
</bean>



<!-- 2.Dao-->
<bean name="accountDao" class="cn.itcast.dao.AccountDaoImpl" >
    <property name="dataSource" ref="dataSource" ></property>
</bean>
<!-- 3.Service-->
<bean name="accountService" class="cn.itcast.service.AccountServiceImpl" >
    <property name="ad" ref="accountDao" ></property>
    <property name="tt" ref="transactionTemplate" ></property>
</bean>  

</beans>

Manual annotation injection into applicationContext2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">

<!-- 指定spring读取db.properties配置 -->
<context:property-placeholder location="classpath:db.properties"  />

<!-- 事务核心管理器,封装了所有事务操作. 依赖于连接池 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
    <property name="dataSource" ref="dataSource" ></property>
</bean>
<!-- 事务模板对象 -->
<bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate" >
    <property name="transactionManager" ref="transactionManager" ></property>
</bean>

<!-- 开启使用注解管理aop事务 -->
<tx:annotation-driven/>

<!-- 1.将连接池 -->
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
    <property name="jdbcUrl" value="${jdbc.jdbcUrl}" ></property>
    <property name="driverClass" value="${jdbc.driverClass}" ></property>
    <property name="user" value="${jdbc.user}" ></property>
    <property name="password" value="${jdbc.password}" ></property>
</bean>



<!-- 2.Dao-->
<bean name="accountDao" class="cn.itcast.dao.AccountDaoImpl" >
    <property name="dataSource" ref="dataSource" ></property>
</bean>
<!-- 3.Service-->
<bean name="accountService" class="cn.itcast.service.AccountServiceImpl" >
    <property name="ad" ref="accountDao" ></property>
    <property name="tt" ref="transactionTemplate" ></property>
</bean>  

</beans>

DAO layer: target objects
AccountDao and AccountDaoImpl

package cn.itcast.dao;

public interface AccountDao {

    //加钱
    void increaseMoney(Integer id,Double money);
    //减钱
    void decreaseMoney(Integer id,Double money);
}

package cn.itcast.dao;

import org.springframework.jdbc.core.support.JdbcDaoSupport;

public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao  {

    @Override
    public void increaseMoney(Integer id, Double money) {

        getJdbcTemplate().update("update t_account set money = money+? where id = ? ", money,id);

    }

    @Override
    public void decreaseMoney(Integer id, Double money) {

        getJdbcTemplate().update("update t_account set money = money-? where id = ? ", money,id);
    }

}

service layer: business processing
AccountService and AccountServiceImpl

package cn.itcast.service;

public interface AccountService {

    //转账方法
    void transfer(Integer from,Integer to,Double money);

}

package cn.itcast.service;

import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import cn.itcast.dao.AccountDao;

@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=true)
public class AccountServiceImpl implements AccountService {

    private AccountDao ad ;
    private TransactionTemplate tt;
    //只读属性改成可操作
    @Override
    @Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
    public void transfer(final Integer from,final Integer to,final Double money) {
                //减钱
                ad.decreaseMoney(from, money);
                int i = 1/0;
                //加钱
                ad.increaseMoney(to, money);
    }


/*  @Override
    public void transfer(final Integer from,final Integer to,final Double money) {

        tt.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus arg0) {
                //减钱
                ad.decreaseMoney(from, money);
                int i = 1/0;
                //加钱
                ad.increaseMoney(to, money);
            }
        });


    }
*/
    public void setAd(AccountDao ad) {
        this.ad = ad;
    }

    public void setTt(TransactionTemplate tt) {
        this.tt = tt;
    }



}

Test class:
xml configuration test class

package cn.itcast.tx;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import cn.itcast.service.AccountService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Demo {
        @Resource(name="accountService")
    private AccountService as;

    @Test
    public void fun1(){

        as.transfer(1, 2, 100d);

    }
}

Annotate the test class:

package cn.itcast.tx;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import cn.itcast.service.AccountService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class Demo2 {
        @Resource(name="accountService")
    private AccountService as;

    @Test
    public void fun1(){

        as.transfer(1, 2, 100d);

    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325687143&siteId=291194637