Spring事务

事务定义接口

事务定义接口TransactionDefinition中定义了事务描述相关的三类常量:事务隔离级别、事务传播行为、事务默认超时时限、以及对它们的操作。

事务隔离级别常量5个(掌握)

ISOLATION_DEFAULT:采用默认的事务隔离级别,Mysql默认为ISOLATION_REPEATABLE_READ,Oracle默认为ISOLATION_READ_COMMITTED

ISOLATION_READ_UNCOMMITTED:读未提交,未解决任何并发问题

ISOLATION_READ_COMMITTED:读已提交,解决脏读,存在不可重复读与幻读

ISOLATION_REPEATABLE_READ:可重复读,解决脏读、存在幻读

ISOLATION_SERIALIZABLE:串行化,不存在并发问题

事务的超时时间:

表示一个方法最长的执行时间,如果方法执行时超过了时间,事务就回滚,

单位秒,整数值,默认-1

事务的传播行为7个:

控制业务是不是有事务的,是什么样的事务,表示你的业务方法调用时,事务在方法之间是如何使用的

PROPAGATION_REQUIRED:指定的方法必须在事务内执行。若当前存在事务,就加入到当前事务,若当前没有事务,则创建一个新事物,这种传播行为是最常见的选择,也是Spring默认的事务传播行为

PROPAGATION_REQUIRES_NEW:总是新建一个事务,若当前存在事务,就将当前事务挂起,直到新事务执行完毕

PROPAGATION_SUPPORTS:指定的方法支持当前事务,若当前没有事务,也可以以非事务方式执行

PROPAGATION_MANDATORY

PROPAGATION_NESTED

PROPAGATION_NEVER

PROPAGATION_NOT_SUPPORTED

使用Spring的事务注解管理事务

通过@Transactional注解方式,可将事务添加到public方法中,实现事务管理

@Transactional的所有可选属性如下

propagation:用于设置事务传播性,该属性类型为propagation枚举,默认值为Propagation.REQUIRED

isolation:用于设置事务的隔离级别,该属性类型为lsolation枚举,默认值为lsolation.DEFAULT

readOnly:用于设置该方法对数据库的操作是否是只读的,该属性为boolean,默认值为false

timeout:用于设置本操作与数据库连接超时时限,单位为秒,类型int,默认值为-1,即没有时限

rollbackFor:指定需要回滚的异常类,类型为Class[],默认值为空数组,当然,若只有一个异常类时,可以不使用数组。

noRollbackFor:指定不需要回滚的异常类,类型为Class[],默认值为空数组

noRollbackForClassName:指定不需要回滚的异常类类名,类型为String[],默认值为空数组

@Transactional(
            propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            readOnly = false,
            //rollbackFor表示发生指定异常一定回滚
            rollbackFor = {
                    NullPointerException.class,NullPointerException.class
            }
    )

注意,@Transactional若用在方法上,只能用在public方法上,对于其他非public方法,如果加上了注解@Transactional,虽然Spring不会报错,但不会将指定事务添加到该方法中,因为Spring会忽略掉所有非public方法上的@Transactiona注解

使用Spring自带@Transactional注解的步骤:

1.需要声明事务管理器对象

<bean id="xx" class="DataSourceTransactionManager"/>

<!--使用spring的事务处理-->
    <bean id="TransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--连接数据库,指定数据源-->
        <property name="dataSource" ref="MyDataSource"/>
    </bean>

2.开启事务注解驱动,告诉spring框架,要使用注解的方式管理驱动

       spring使用aop机制,创建@Transactional所在的类代理对象,给方法加入事务的功能

        spring给业务方法加入事务,在你业务方法执行之前,先开启事务,在业务方法之后提交或回滚事务,使用aop的环绕通知

<!--开启事务注解驱动,告诉spring用注解管理事务,创建代理对象-->
    <tx:annotation-driven transaction-manager="TransactionManager"/>

 3.在方法上面加入@Transactional

package com.bjpowernode.service.impl;

import com.bjpowernode.dao.GoodsDao;
import com.bjpowernode.dao.SaleDao;
import com.bjpowernode.domian.Goods;
import com.bjpowernode.domian.Sale;
import com.bjpowernode.service.GoodsService;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

public class GoodsServiceImpl implements GoodsService {
    private SaleDao saleDao;
    private GoodsDao goodsDao;

    public void setSaleDao(SaleDao saleDao) {
        this.saleDao = saleDao;
    }

    public void setGoodsDao(GoodsDao goodsDao) {
        this.goodsDao = goodsDao;
    }
    @Transactional(
            propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            readOnly = false,
            //rollbackFor表示发生指定异常一定回滚
            rollbackFor = {
                    NullPointerException.class,NullPointerException.class
            }
    )
    @Override
    public void buy(Integer goodsId, Integer nums) {
        //记录销售信息,向sale表添加记录
        Sale sale = new Sale();
        sale.setGid(goodsId);
        sale.setNums(nums);
        saleDao.insertSale(sale);
        //更新库存
        Goods goods = goodsDao.selectGoods(goodsId);
        if(goods == null){
        throw  new NullPointerException("标号是:"+goodsId+",的商品不存在");
        }else if (goods.getAmount()<nums){
            throw new NullPointerException("编号是:"+goodsId+",库存不足");
        }
        //修改库存
        Goods goods1 = new Goods();
        goods1.setId(goodsId);
        goods1.setAmount(nums);
        goodsDao.updateGoods(goods1);
        System.out.println("===buy()方法执行完毕 ===");
    }
}

---------------------------------------------------------------

使用aspectJ框架功能,在spring配置文件中声明类,方法需要的事务,这种方式业务方法和事务配置完全分离

实现步骤:

都是在spring配置文件.xml文件中实现

1.要使用aspectJ框架,需要加入依赖

pom中加入aspectj框架依赖

 <!--aspectj依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>

2.声明事务管理器对象

在spring配置文件中添加

 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--声明数据源,(数据库连接对象)-->
        <property name="dataSource" ref="MyDataSource"/>
    </bean>

3.声明方法需要的事务类型(配置方法的事务属性,传播行为,隔离级别,超时)

在spring配置文件中添加

  <!--
    声明事务属性(隔离级别,传播行为,超时时间)
    id:自定义名称
    transaction-manager:事务管理器对象的id
    <tx:advice>和</tx:advice>之间配置内容的
    -->
    <tx:advice id="myAdvice" transaction-manager="transactionManager">
        <tx:attributes><!--配置事务属性-->
            <!--tx:method:给具体的方法配置事务,method可以有多个,给不同的方法配置事务
                name:完整的方法名
                propagation:传播行为
                isolation:隔离级别
                rollback-for:指定异常的全限定类名,发生异常一定回滚
            -->
            <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT"
                       rollback-for="NullPointerException,NullPointerException"/>
        </tx:attributes>
    </tx:advice>

4.配置aop:指定哪些类要创建代理

在spring配置文件中添加

  <!--配置aop指明哪个类需要添加事务-->
    <aop:config>
        <!--配置切入表达式,指定哪些包中的类,要使用事务
            id:切入点表达式名称,唯一值
            expression:切入点表达式
        -->
        <aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))"/>
        <!--配置增强器:关联adivce和pointcut
        advice-ref:关联,上面<tx:advice>配置的内容
        pointcut-ref:切入点表达式id
        -->
        <aop:advisor advice-ref="myAdvice" pointcut-ref="servicePt"/>
    </aop:config>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没有腰的嘟嘟嘟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值