美文网首页
Spring事务管理

Spring事务管理

作者: 磊_5d71 | 来源:发表于2018-10-24 12:38 被阅读0次

事务

  • 事务一般特指数据库事务,是指作为一个程序执行单元执行的一系列操作,要么完全执行,要么完全不执行。

事务四大特性

1、原子性:一个事务(可能包含多条SQL)是一个不可分割的工作单位。
2、一致性:事务必须是使数据库从一个一致性状态变到另一个一致性状态。
3、隔离性:一个事务的执行不能被其他事务干扰。
4、持久性:一个事务一旦提交,它对数据库中数据的改变应该是永久性的。

Mysql事务处理

  • 只有Innodb存储引擎支持事务。
  • Mysql默认以自动提交模式运行。


    图片.png
    图片.png
    图片.png
图片.png

事务隔离级别

图片.png
  • 查看隔离级别:select @@transaction_isolation
--设置事务隔离级别
SET SESSION TRANSACTION ISOLATION  LEVEL READ UNCOMMITTED;

-- 脏读
-- 事务A
begin;
select stock from products where id  = '100001';
ROLLBACK;

-- 事务B
BEGIN;
UPDATE products set stock=0 where id = '100001';
ROLLBACK;


-- 不可重复读
-- 事务A
BEGIN;
select stock from products where id  = '100001'; //第一步:第一次查询
select stock from products where id  = '100001';//第三步:第二次查询
ROLLBACK;

-- 事务B
BEGIN;
UPDATE products SET STOCK = 0 WHERE ID = '100001'; //第二步:事务B提交
COMMIT;

--幻读
--事务A
BEGIN;
UPDATE products SET stock = 0;   //第一步
select * from products; //第三步
ROLLBACK;
--事务B
BEGIN;
INSERT INTO products VALUES('100005','',1999,100,'正常'); //第二步
COMMIT;

JDBC事务处理

Connection接口
  • JDBC的事务处理是基于Connection的,JDBC通过Connection对象进行事务管理。
  • JDBC默认事务处理行为是自动提交。
事务相关方法
  • setAutoCommit
    设置自动提交
  • commit
    提交事务
  • rollback
    回滚事务
package com.alan.dao;


import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class OrderTest {


    private String driver = "com.mysql.cj.jdbc.Driver";
    private String url = "jdbc:mysql:///os?characterEncoding=utf8";
    private String userName = "root";
    private String password = "root";


    @Test
    public void addOrder(){

        Connection connection = null;
        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url,userName,password);
            //封装为一个事务
            connection.setAutoCommit(false);
            Statement statement = connection.createStatement();
            statement.execute("insert into orders values('100002','100001',2,2499,now(),null,null,'刘备','1330000000','成都','待发货')");
            statement.execute("update products set stock= stock-2 where id='100001'");
            statement.close();
            //提交事务
            connection.commit();

        } catch (Exception e) {
            try {
                connection.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally {
            if(connection != null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            connection = null;
        }
    }

}
图片.png

Spring事务处理API

图片.png 图片.png
  • 持久层提供基本的操作,业务层进行事务的封装处理

Spring事务处理-基于底层API

图片.png
  • OrderService
package com.alan.service;

import com.alan.entity.Order;

public interface OrderService {

    void addOrder(Order order);
}
  • OrderServiceImpl
package com.alan.service.impl2;

import com.alan.dao.OrderDao;
import com.alan.dao.ProductDao;
import com.alan.entity.Order;
import com.alan.entity.Product;
import com.alan.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import java.util.Date;


@Service
public class OrderServiceImpl implements OrderService {


    //通过Spring自动注入
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private ProductDao productDao;
    //事务管理器
    @Autowired
    private PlatformTransactionManager transactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;


    @Override
    public void addOrder(Order order) {

        order.setCreateTime(new Date());
        order.setStatus("待付款");


        //开启事务
        TransactionStatus transaction = transactionManager.getTransaction(transactionDefinition);

        try {
            //以下两个操作用事务封装在一起
            orderDao.insert(order);
            Product product = productDao.select(order.getProductsId());
            product.setStock(product.getStock() - order.getNumber());
            productDao.update(product);

            //提交事务
            transactionManager.commit(transaction);
        }catch (Exception e){
            //碰到异常,回滚事务
            e.printStackTrace();
            transactionManager.rollback(transaction);
        }
    }
}

编程式处理方式二

<?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"
       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">

    <import resource = "applicationContext.xml"/>

    <context:component-scan base-package="com.alan.service.impl2"/>

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

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

</beans>
package com.alan.service.impl2;

import com.alan.dao.OrderDao;
import com.alan.dao.ProductDao;
import com.alan.entity.Order;
import com.alan.entity.Product;
import com.alan.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Date;


@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderDao orderDao;
    @Autowired
    private ProductDao productDao;
    @Autowired
    private TransactionTemplate transactionTemplate;

    public void addOrder(final Order order) {
        order.setCreateTime(new Date());
        order.setStatus("待付款");

        transactionTemplate.execute(new TransactionCallback() {
            public Object doInTransaction(TransactionStatus transactionStatus) {
                try {
                    orderDao.insert(order);
                    Product product = productDao.select(order.getProductsId());
                    product.setStock(product.getStock() - order.getNumber());
                    productDao.update(product);
                }catch (Exception e){
                    e.printStackTrace();
                    transactionStatus.setRollbackOnly();
                }
                return null;
            }
        });

    }
}

Spring事务处理-基于拦截器 TransactionInterceptor 方式

  • Spring的声明式事务处理是建立在AOP的基础之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
  • 开发中建议使用声明式事务,方便后期代码维护。
  • 实现类
package com.alan.service.impl;

import com.alan.dao.OrderDao;
import com.alan.dao.ProductDao;
import com.alan.entity.Order;
import com.alan.entity.Product;
import com.alan.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import java.util.Date;


@Service
public class OrderServiceImpl implements OrderService {


    //通过Spring自动注入
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private ProductDao productDao;

    @Override
    public void addOrder(Order order) {

        //声明式,代码只是业务层的。
        order.setCreateTime(new Date());
        order.setStatus("待付款");

        orderDao.insert(order);
        Product product = productDao.select(order.getProductsId());
        product.setStock(product.getStock() - order.getNumber());
        productDao.update(product);
    }
}
  • XML配置
<?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"
       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">

    <import resource = "applicationContext.xml"/>

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


    <!--目标对象-->
    <bean id="orderServiceTarget"  class="com.alan.service.impl.OrderServiceImpl"></bean>

    <!--配置拦截器-->
    <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">

        <!--配置事务管理器-->
        <property name="transactionManager" ref="transactionManager"></property>
        <!--事务属性-->
        <property name="transactionAttributes">
            <props>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="search*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
    <!--将上面二者关联起来-->
    <bean id="orderService" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--配置目标类-->
        <property name="target" ref="orderServiceTarget"></property>
        <!--配置拦截器名称-->
        <property name="interceptorNames">
            <list>
                <idref bean="transactionInterceptor"></idref>
            </list>
        </property>
    </bean>
</beans>

Spring事务处理-基于拦截器 TransactionProxyFactoryBean 方式(对上一种的简化方式)

<?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"
       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">

    <import resource = "applicationContext.xml"/>

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


    <!--目标对象-->
    <bean id="orderServiceTarget"  class="com.alan.service.impl.OrderServiceImpl"></bean>

    <!--组合配置-->
    <bean id="orderService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager" ref="transactionManager"></property>

        <!--目标类配置-->
        <property name="target" ref="orderServiceTarget"></property>

        <!--拦截器配置-->
        <property name="transactionAttributes">
            <props>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="search*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>


</beans>

Spring基于<tx>命名空间的声明式事务处理 (实际用的多)

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

    <import resource = "applicationContext.xml"/>

    <!--开启自动扫描-->
    <context:component-scan base-package="com.alan.service.impl"></context:component-scan>

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

    <!--配置通知,也就是拦截后要处理的方法-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--name中为实现类里面具体的方法-->
            <tx:method name="get*" propagation="REQUIRED" read-only="true"/>
            <tx:method name="find*" propagation="REQUIRED" read-only="true"/>
            <tx:method name="search*" propagation="REQUIRED" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!--aop相关配置-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pointcut" expression="execution(* com.alan.service.impl.OrderServiceImpl.*.*(..))"></aop:pointcut>
        <!--关联起来-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"></aop:advisor>
    </aop:config>
</beans>

Spring基于@Transactional声明事务管理

相关文章

网友评论

      本文标题:Spring事务管理

      本文链接:https://www.haomeiwen.com/subject/rcdnzftx.html