spring事务处理


title: spring事务处理
tag: JAVA


1.几个问题 2.Spring事务处理

1.几个问题

1. 什么是事务?

数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。

2. 什么时候要用到事务?

当一个操作涉及多个表或者多条查询语句时,比如转账。java代码中,service类的业务方法中用到多个dao方法,执行多个sql语句,所以开发中service类业务方法上要用到事务

3. 通常使用jdbc和mybatis访问数据库怎么处理事务?

  • jdbc处理事务:conn.commit(),conn.rollback
  • mybatis处理事务:SqlSession.commit,SqlSession.rollback

4. 3中事务的处理方式有什么不足?

  • 不同的数据库访问技术处理事务的对象、方法不同,程序员需要了解各种数据库访问技术处理事务的原理
  • 程序员需要掌握多种数据库中事务的处理逻辑。什么时候提交事务,什么时候回滚事务

5. 怎么解决不足?

Spring提供了一种处理事务的统一模型,我们只需要告诉Spring我们用的事mybatis还是hibernate还是其他的数据库访问技术? Spring来进行commit和rollback,我们只需要掌握Spring怎么用就行了。Spring为程序员提供的机制是声明式事务:程序员只需要把事务相关的资源和内容提供给Spring,Spring就知道怎么提交怎么回滚了,我们几乎不用写代码

6. 使用Spring处理事务,我们需要做什么怎么做?

  • 前面说声我们只需要把事务相关的资源和内容告诉spring即可,那么什么是事务相关的资源和内容呢?

1. 事务管理器对象,负责事务提交和回滚。

它是一个接口PlatformTransactionManager,不同的数据库访问技术对应不同的实现类,mybatis对应的实现类是DataSourceTransactionManager。所以只需在spring配置文件中使用bean标签声明即可。

2. 业务方法所需事务的属性。

包括:事务的隔离级别、事务的超时时间、事务的传播行为

2.Spring事务处理

1. 使用Spring的@Transactional注解管理事务

适合中小项目,在service实现类的业务方法上加上@Transactional注解,表示该方法是一个事务,注解的属性表示事务的属性

步骤一:配置事务管理器对象

   <!--使用spring的事务处理-->
    <!--1.声明事务处理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--连接的数据库-->
        <property name="dataSource" ref="dataSource"/>
    </bean>

步骤二:开启事务注解驱动

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

步骤三:在方法上加上注解

package xyz.guawaz.service.impl;

import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import xyz.guawaz.dao.GoodsDao;
import xyz.guawaz.dao.SaleDao;
import xyz.guawaz.domain.Goods;
import xyz.guawaz.domain.Sale;
import xyz.guawaz.exception.NotEnoughException;
import xyz.guawaz.service.BuyGoodsService;

public class BuyGoodsServiceImpl implements BuyGoodsService {
    private GoodsDao goodsDao;
    private SaleDao saleDao;

    public void setGoodsDao(GoodsDao goodsDao) {
        this.goodsDao = goodsDao;
    }

    public void setSaleDao(SaleDao saleDao) {
        this.saleDao = saleDao;
    }
    @Transactional(
            propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            readOnly = false,
            rollbackFor = {
                    NullPointerException.class,NotEnoughException.class
            }
    )
    @Override
    public void buy(int goodsId, int nums) {
        System.out.println("==========buy方法的开始==========");
        //记录销售信息,向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 NotEnoughException("编号是"+goodsId+"的商品库存不足");
        }

        //修改库存
        Goods buyGoods = new Goods();
        buyGoods.setId(goodsId);
        buyGoods.setAmount(nums);
        goodsDao.updateGoods(buyGoods);
        System.out.println("==========buy方法的结束==========");
    }
}

2. 使用AspectJ的AOP配置管理事务

适合大型项目,有很多类和方法需要大量的配置事务,使用AapectJ框架的功能,在Spring配置文件中声明类、方法需要的事务,这种方式业务方法和事务配置完全分离

步骤一:引入AspectJ依赖

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

步骤二:配置事务管理器对象

   <!--使用spring的事务处理-->
    <!--1.声明事务处理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--连接的数据库-->
        <property name="dataSource" ref="dataSource"/>
    </bean>

步骤三: 用tx:advice标签配置业务方法的事务及其属性

隔离级别、传播行为、超时时间

 <tx:advice id="myAdvice" transaction-manager="transactionManager">
        <tx:attributes><!--配置事务属性-->
            <!--name;方法名称,可以写
                    1.完整的方法名称,不带包和类
                    2.通配符,*代表任意字符
            -->
            <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT"
                       rollback-for="java.lang.NullPointerException,xyz.guawaz.exception.NotEnoughException"/><!--给具体的方法配置事务属性,method可以有多个-->
            <tx:method name="add*" propagation="REQUIRES_NEW"/>
            <tx:method name="remove*" propagation="REQUIRED"/>
            <tx:method name="modify*" propagation="REQUIRED"/>
            <tx:method name="query*" propagation="SUPPORTS" read-only="true"/>
        </tx:attributes>
    </tx:advice>

步骤四:用aop:config标签配置AOP,指定哪些类要使用事务为其创建代理对象

配置切入点表达式和增强器

    <aop:config>
        <!--配置切入点表达式,指定哪些包中类要使用事务
            id:切入点表达式的名称
            expression:切入点表达式,指定哪些类要配置事务,aspectj会创建代理对象
        -->
        <aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))"/>
        <!--配置增强器,关联advice和pointcut-->
        <aop:advisor advice-ref="myAdvice" pointcut-ref="servicePt"/>
    </aop:config>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值