Spring事务管理

192 阅读4分钟

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

什么是事务

  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:新建事务,如果当前存在事务,把当前事务挂起。
  • PROPAGATION_NOT_ 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
  • 声明式事务处理