Spring 事务管理

Posted Do_GH

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 事务管理相关的知识,希望对你有一定的参考价值。

文章目录

PlatformTransactionManager

spring框架也提供了一套完整的事务管理方案。其中主要以PlatformTransactionManager类为核心类,该类提供了三个方法:

  • TransactionStatus getTransaction(TransactionDefinition definition)根据指定的传播行为,返回当前活动的事务或创建一个新的事务,参数为TransactionDefinition接口,该接口主要定义了事务传播的方式、隔离等级和事务超时时间。返回一个事务的状态TransactionStatus类。
  • commit(TransactionStatus status)提交当前事务
  • rollback(TransactionStatus status)回滚当前事务

PlatformTransactionManager有三个实现类DataSourceTransactionManager用于绑定jdbc数据源,HibernateTransactionManager用于绑定Hibernate框架,JpaTransactionManager

TransactionDefinition

该类主要定义了事务传播方式、隔离等级和事务超时时间

属性

  • 事务传播方式
传播方式描述
PROPAGATION_REQUIRED支持当前事务,如果当前没有事务,则创建一个新的事务0
PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,则以非事务方式执行1
PROPAGATION_MANDATORY支持当前事务,如果当前没有事务,就抛出异常2
PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起3
PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起4
PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常5
PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行
如果当前没有事务则新建一个事务
6
  • 事务隔离等级
    spring定义的隔离级别与数据库相同,也分为4个级别作用效果也相同
隔离等级描述
ISOLATION_DEFAULT使用所使用默认数据库的隔离等级-1
ISOLATION_READ_UNCOMMITTED读未提交1
ISOLATION_READ_COMMITTED读已提交2
ISOLATION_REPEATABLE_READ可重复读4
ISOLATION_SERIALIZABLE串行化8
  • 事务的超时时间
    若某一事务在一定时间内未响应,则会直接回滚该事务
超时时间描述
TIMEOUT_DEFAULT默认超时时间(30秒)-1

方法

  • int getIsolationLevel()获取事务隔离等级(数值)
  • String getName()获取当前事务的名称
  • int getPropagationBehavior()获取事务的传播行为(数值)
  • int getTimeout()获取事务的超时时间
  • Boolean isReadOnly()是否优化为只读事务

SpringAPI事务管理方式

创建底层的spring的配置文件注册JDBC

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

    <!-- 创建数据库连接信息 -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/os"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 扫描dao包下所有的注解 -->
    <context:component-scan base-package="com.spring.transaction.dao"/>

</beans>

使用底层方法管理事务

再创建spring事务底层类的Bean实现

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

    <!-- 引入applicationContext配置 -->
    <import resource="applicationContext.xml"/>

    <!-- 注册事务管理平台,使用DataSourceTransactionManager实现类并指定数据源 -->
    <bean id="transactionManagement" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="transactionDefinition" class="org.springframework.transaction.support.DefaultTransactionDefinition">
        <!-- 注册事务传播行为类时,一般采用默认设置即可,如果需要修改可以设置property属性来进行修改-->
        <property name="isolationLevelName" value="ISOLATION_DEFAULT"/>
        <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
        <property name="timeout" value="30"/>
    </bean>
</beans>

创建业务实现类

package com.spring.transaction.service.impl;

import com.spring.transaction.dao.OrderDao;
import com.spring.transaction.dao.ProductDao;
import com.spring.transaction.entity.Order;
import com.spring.transaction.entity.Product;
import com.spring.transaction.service.OrderService;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import javax.annotation.Resource;
import java.util.Date;

public class OrderServiceImpl implements OrderService 
    @Resource
    private OrderDao orderDao;
    @Resource
    private ProductDao productDao;

    @Resource
    private PlatformTransactionManager transactionManager;
    @Resource
    private TransactionDefinition transactionDefinition;

    public void addOrder(Order order) 
        // 创建事务
        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);
        
    


将需要处理的业务逻辑放在try...catch...中,如果在处理业务时发生了异常就可以调用rollback()方法进行回滚

使用TransactionTemplate管理事务

创建一个新的spring配置,配置TransactionTemplate的Bean类,该类是简化编程式事务界定和事务异常处理的模板类,它的核心方法为execute(org.springframework.transaction.support.TransactionCallback<T>),此模板处理事务生命周期和可能的异常,这样TransactionCallback实现和调用代码都不需要显式地处理事务。

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

    <!-- 引入applicationContext配置 -->
    <import resource="applicationContext.xml"/>

    <!-- 添加自动扫描 -->
    <context:component-scan base-package="com.spring.transaction.service"/>

    <!-- 注册事务管理平台,使用DataSourceTransactionManager实现类并指定数据源 -->
    <bean id="transactionManagement" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 使用TransactionTemplate管理事务,需要指定事务管理平台 -->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManagement"/>
    </bean>
</beans>

TransactionTemplate允许编写底层数据访问对象,这些对象使用诸如JDBC数据源之类的资源,但本身不支持事务。相反,它们可以隐式的参与高级应用程序服务利用该类处理的事务,并通过内部类回调对象调用低级服务。

package com.spring.transaction.service.impl;

import com.spring.transaction.dao.OrderDao;
import com.spring.transaction.dao.ProductDao;
import com.spring.transaction.entity.Order;
import com.spring.transaction.entity.Product;
import com.spring.transaction.service.OrderService;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;

public class OrderServiceImpl1 implements OrderService 
    @Resource
    private OrderDao orderDao;
    @Resource
    private ProductDao productDao;

    @Resource
    private TransactionTemplate transactionTemplate;

    public void addOrder(final Order order) 
        transactionTemplate.execute(new TransactionCallback<Object>() 
            public Object doInTransaction(TransactionStatus transactionStatus) 
                orderDao.insert(order);
                Product product = productDao.select(order.getProductsId());
                product.setStock(product.getStock() - order.getNumber());
                productDao.update(product);
                
                return null;
            
        );
    

Spring 声明式管理事务

除了使用API的形式显示的方法管理事务,spring还提供在配置文件中声明管理事务。这种方法主要建立在AOP的基础之上,本质上就是对需要进行事务管理的方法进行拦截,对其增强。这样业务层的实现类就会更加简便,方便后期维护。

基于TransactionInterceptor的事务管理

<?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">
    
    <!-- 引入applicationContext配置 -->
    <import resource="applicationContext.xml"/>
    
    <!-- 添加自动扫描 -->
    <context:component-scan base-package="com.spring.transaction.service"/>

    <!-- 注册事务管理平台,使用DataSourceTransactionManager实现类并指定数据源 -->
    <bean id="transactionManagement" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
    <!-- 注册实现类 -->
    <bean id="orderServiceTarget" class="com.spring.transaction.service.impl.OrderServiceImpl"/>

	<!-- 设置事务拦截器 -->
    <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
		<!-- 设置事务管理器 -->
        <property name="transactionManager" ref="transactionManager"/>
        <!-- 设置事务属性,使用props标签利用键值对的形式为属性赋值,key描述实现类的方法,支持通配符 -->
        <property name="transactionAttributes">
            <props>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
            </props>
        </property>
    </bean>

	<!-- 使用代理类,设置目标类,并增加拦截器 -->
    <bean id="orderService" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="orderServiceTarget"/>
        <!-- 如果有多个拦截器使用list标签 -->
        <property name="interceptorNames">
            <list>
                <idref bean="transactionInterceptor"/>
            </list>
        </property>
    </bean>
</beans>

简单来说就是利用AOP对业务实现类进行增强,只需要创建TransactionInterceptor的实例并配置事务属性即可

基于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">
    
    <!-- 引入applicationContext配置 -->
    <import resource="applicationContext.xml"/>
    
    <!-- 添加自动扫描 -->
    <context:component-scan base-package="com.spring.transaction.service"/>

    <!-- 注册事务管理平台,使用DataSourceTransactionManager实现类并指定数据源 -->
    <bean id="transactionManagement" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
    <!-- 注册实现类 -->
    <bean id="orderServiceTarget" class="com.spring.transaction.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>
            </props>
        </property>
        <!-- 指定需要增强的目标类 -->
        <property name="target" ref="orderServiceTarget"/>
    </bean>
</beans>

基于<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">
    <!-- 引入applicationContext配置 -->
    <import resource="applicationContext.xml"/>
    
    <!-- 添加自动扫描 -->
    <context:component-scan base-package="com.spring.transaction.service"/>

    <!-- 注册事务管理平台,使用DataSourceTransactionManager实现类并指定数据源 -->以上是关于Spring 事务管理的主要内容,如果未能解决你的问题,请参考以下文章

Spring事务看这一篇就够了!!(Spring事务特征+Spring事务管理+实现+Spring七种事务传播行为+集成MyBatis)

Spring事务看这一篇就够了!!(Spring事务特征+Spring事务管理+实现+Spring七种事务传播行为+集成MyBatis)

spring怎么进行的事务管理,求指导?

Spring_8-Spring事务管理

Spring的学习(Spring事务管理)

什么叫做spring的声明式事务