Spring事务管理

内容纲要

概念:事务一般特指数据库事务,是指作为一个程序执行单元执行的一系列操作,要么完全执行,要么完全不执行
在业务层封装事务

什么是事务

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

    MySQL事务处理

    • 基本规则
    • MySQL中只有使用了Innodb数据库引擎的数据库或表才支持事务。
    • MySQL默认以自动提交(autocommit)模式运行。
      语句:
    • BEGIN(STARTTRANSACTION) 显式地开启一个事务
    • COMMIT 提交事务,并使用对数据库进行的所有修改变为永久性的
    • ROLLBACK 回滚事务,并撤销正在进行的所有未提交的修改

      事务并发问题

    • 脏读

      解决:只能读取永久性数据,不能读取内存中的数据
    • 不可重复读

      解决:锁行
    • 幻读

      解决:锁表

      事务隔离级别

事务隔离级别 脏读 不可重复读 幻读
读未提交( read-uncommitted )
读已提交( read-committed )
可重复读( repeatable-read )
串行化( serializable )
  • 语句
    --- select@@tx_isolation

    • 查询默认隔离级别
      --- set session transaction isolation level XXX
    • 设置当前会话隔离级别

      JDBC事务处理

  • Connection接口

  • JDBC的事务处理是基于Connection的,JDBC通过COnnection对象进行事务管理

  • JDBC默认事务处理行为是自动提交

  • 事务相关方法

  • setAutoCommit

  • 设置自动提交

  • commit

  • 事务提交

  • rollback

  • 回滚事务

    JDBC事务隔离级别

  • TRANSACTION_NONE(不支持事务) 0;

  • TRANSACTION_READ_UNCOMMITTED(读未提交)1;

  • TRANSACTION_READ_COMMITTED(读已提交)2;

  • TRANSACTION_REPEATABLE_READ(可重复读)4;

  • TRANSACTION_SERIALIZABLE (串行化)8;

  • 事务隔离级别设置

  • getTransactionIsolation 获取当前隔离级别(只能获取到上面的0 1 2 4 8 )

  • setTransactionIsolation 设置隔离级别 默认为4(同上)

    Spring事务处理API

    TransationDefinition接口

  • 隔离级别

  • ISOLATION_DEFAULT(使用数据库默认)

  • ISOLATION_READ_UNCOMMITTED

  • ISOLATION_READ_COMMITTED

  • ISOLATION_REPEATABLE_READ

  • ISOLATION_SERIALIZABLE

  • 默认超时

  • TIMEOUT_DEFAULT : 30秒

    事务传播行为

  • PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。(Spring默认)

  • PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。

  • PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。

  • PROPAGATION_REQUIRES NEW:新建事务,如果当前存在事务,把当前事务挂起。

  • PROPAGATIONNOT SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

  • PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

  • PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,就新建一个事务。

    Spring编程式事务处理

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://47.114.2.235:3306/Spring?useUnicode=true&characterEncoding=utf-8"/>
    <property name="username" value="Spring"/>
    <property name="password" value="Spring"/>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource" />
    </bean>
    <context:component-scan base-package="dao"/>
  • 基于底层API的编程式事务管理

  • PlatformTransactionManager 事务管理器

  • TransactionDefinition 事务的一些基础信息,如超时时间、隔离级别、传播属性等

  • TransactionStatus 事务的一些状态信息,如是否一个新的事务、是否已被标记为回滚

  • 基于TransactionTemplate的编程式事务管理

//OrderServiceImpl
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderDao orderDao;
    @Autowired
    private ProductDao productDao;
    @Autowired
    private PlatformTransactionManager transactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;

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

        TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
        try {
            orderDao.insert(order);
            Product product = productDao.select(order.getProductsId());
            product.setStock(product.getStock() - order.getNumber());
            productDao.update(product);
            transactionManager.commit(transactionStatus);
        } catch (Exception e) {
            transactionManager.rollback(transactionStatus);
        }
    }
}
//XML
<import resource="spring-dao.xml"/>

<context:component-scan base-package="service.impl2"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionDefinition" class="org.springframework.transaction.support.DefaultTransactionDefinition">
    <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
</bean>
  • TransactionTemplate(为简化步骤而存在)
//OrderServiceImpl
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private ProductDao productDao;
    @Autowired
    private TransactionTemplate transactionTemplate;
    public void addOrder(Order order) {
        order.setCreateTime(new Date());
        order.setStatus("代付款");
        transactionTemplate.execute(new TransactionCallback() {
            @Override
            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) {
                    transactionStatus.setRollbackOnly();
                }
                return null;
            }
        });
    }
}
//XML
<import resource="spring-dao.xml"/>

<context:component-scan base-package="service.impl1"/>
<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>

Spring声明式事务处理

  • 概述
    一Spring 的声明式事务处理是建立在AOP的基础之上的。其本质是对方法前
    后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
    一建议在开发中使用声明式事务 ,是因为这样可以使得业务代码纯粹干净,方便后期的代码维护
//OrderServiceImpl
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private ProductDao productDao;
    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);
    }
}

基于TransactionInterceptor的声明式事务处理

<import resource="spring-dao.xml"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
<bean id="orderServiceTarget" class="service.impl.OrderServiceImpl"/>
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <property name="transactionManager" ref="transactionManager"/>
    <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 name="interceptorNames">
        <list>
            <idref bean="transactionInterceptor"/>
        </list>
    </property>
</bean>

基于TransactionProxyFactoryBean的声明式事务处理(简化上一方法的配置)

//XML
<import resource="spring-dao.xml"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
<bean id="orderServiceTarget" class="service.impl.OrderServiceImpl"/>
<bean id="orderService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager" ref="transactionManager"/>
    <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>
    <property name="target" ref="orderServiceTarget"/>
</bean>

基于命名空间的声明式事务管理(频繁 更合理)

<import resource="spring-dao.xml"/>
<context:component-scan base-package="service.impl"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
<!--    配置通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <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:config>
<!--        定义切面      execution(* service.impl.*.*(..)):任意返回值  impl包下所有的所有类所有方法的任意返回值还有任意参数-->
    <aop:pointcut id="pointcut" expression="execution(* service.impl.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>

基于@Transactional的声明式事务管理(频繁 更流行)

//XML
<import resource="spring-dao.xml"/>
    <context:component-scan base-package="service.impl3"/>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
<!--    使用tx驱动指定关于事务的注解,并且指定事务管理器-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
//OrderServiceImpl
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private ProductDao productDao;
//    @Transactional 使用默认
    @Transactional(propagation = Propagation.REQUIRED)
    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);
    }
}

总结

  • 事务概念
  • 完成某个业务功能所需的一系列操作。
  • 特性:原子性( atomicity)、 -致性( consistency )、隔离性( isolation)、 持久性( durability )
  • 并发问题:脏读、不可重复读、幻读
  • 事务隔离级别:读未提交( read-uncommitted )、读已提交( read- committed)、可重复读( repeatable-read)、 串行化( serializable )
  • Spring事务处理
  • API
  • 声明式事务处理
THE END
分享
二维码
< <上一篇
下一篇>>