spring快速入门(四)spring事物

spring管理事务

事物的概念
什么是事物,事物是一些sql序列的集合,是多条sql,作为一个整体,
事务指逻辑上的一组操作,这组操作要么全部成功,要么全部失败.
事物有四个特性
原子性,一致性,隔离性,持久性
解释
原子性:意思是不可分割 通俗的说要么全部成功如果有一个失败那全部失败
一致性:操作之前的数据总量变化一致 列 转账: 如果小马转账给小王一千万 如果小马的金额没有变那么小王得到了一千万那
那么就失败不一致 就是操作之前之后数据要一致
隔离性:多个事物操作某一条记录他们之间不会产生影响
持久性:就是提交数据到数据库时就叫持久性

mysql执行事务
beginTransaction 开始事物
insert into student()values....
select * from student where id=1
update school set name=XXX where id=555
endTransaction 事务结束

在程序中事物在哪说明

事物:加在业务类的方法上面(punlic方法上面),表示业务执行时,需要事物的支持

事务管理器

1.不同的数据库访问技术,处理事务是不同的
(1)使用jdbc访问数据库,事务处理

public void updateaccount(){
connection conn =
conn.setAutocommit(false)
stat.insert()
stat.update()
conn.commit()
con.setAutocommit(ture)
}

(2)mybatis执行数据库,处理事务

public void updateAccount(){
SqlSession session=SqlSession.openSession(false);
try{
session.insert(i"insert into student......");
session.update("update school.....")
}catch(Exception e){
   session.rollback();
}
}

spring统一管理事务,把不同的数据库访问技术的事务处理统一起来

使用spring的事务管理器,管理不同数据库访问技术的事务处理,开发人员只需要掌握spring的事物处理一个方案,就可以使用不同的数据库访问技术的事务管理。
管理事物面向的时spring,有spring管理事务,做事物提交,事物回滚。

spring事务管理器

spring框架使用事务管理器对象,管理所有的事物
事物管理器接口:PlatformTranscationManager
作用:定义事物的操作方法,主要是commit(),rollback()
事物管理器有很多实现类:一种数据库的访问技术有一个实现类,由具体完成事物的提交,回滚,
意味着:
jdbc或mysql访问数据库有自己的事物管理器实现类,DataSourceTransactionManager,
hibernate框架,他的事务管理器实现类:hibernateTransactionManager,

spring事物工作方式

spring统一管理事务

事物的提交和回滚的时机

什么时候提交事务,什么时候回滚事务?
当你的业务方法正常执行时,没有异常,事物时正常提交的,如果你的事物抛出运行时异常时,事物是回滚的,

异常分类
Error:严重错误,回滚事物,
Exception:异常类,可以出来的异常情况
1.运行时异常,RuntionException和他的子类都是运行时异常,在程序执行过程中,抛出异常,常见的运行时异常;NullpoinerException,NumberFormException,indexBoundException,ArithmeticException,indexOutBoundException,
2.受查异常:编写Java代码的时候,必须处理的异常,例如IO exception,SQLexception,FileNotFoundexception,

即抛出运行时异常,事物回滚,其他情况默认提交,

spring事物使用的是AOP的环绕通知

环绕通知,可以在目标方法的前后都能增强功能,不需要修改代码,

spring给业务在执行时,增加事物的切面功能
@Around("execution( * 所有的业务类中的方法)")
public object mAround(proceedingJoinPoint pjp){
try{
PlatformTransactionManager.beginTransaction(); //使用事物管理器,开启事物
pjp.proceed(); //执行目标方法 
PlatformTransactionManager.commit(); //业务方法正常执行
}catcha(exception e){
PlatformTransactionManager.rollback(); //事物回滚
}
}

事物定义接口

事物定义接口TransactionDefinition
TransactionDefinition接口,定义了三类常量,定义了有关事务控制的属性,
事物的属性:1.隔离级别,2.传播行为,3.事物的超时
给业务方法说明事物属性,和ACID不一样

隔离级别

隔离级别:控制事物之间影响的程度,
五个值,只有四个隔离级别
在这里插入图片描述

事物的超时

超时时间是以秒为单位,整数值,默认-1,
超时时间:表示一个业务方法最长的执行时间,达到执行时间没有执行完毕,spring事物回滚,

传播行为

传播行为业务在调用时,事物在方法之间的传递和使用,
使用传播行为,标识方法有无事物,

传播行为有七个值
传播行为
1.REQUIRED:spring默认的传播行为,方法在调用时,存在事物就使用当前的事物,如果没有事物,则新建事物,方法在新事物中执行,
2.SUPORTS:支持,有事物可以正常执行,没有事物也可以正常执行,常用查询操作
3.REQUIRES_NEW:方法需要一个新事物,如果调用方法时,存在一个事物,则原来的事物暂停,直到新事物执行完毕,如果方法调用时,没有事物则新建一个事物,在新事物执行代码,

实例,构建一个简单项目

spring框架使用自己的注解@Transaction控制事物

@Transaction 注解,使用注解的属性控制事物(隔离级别,传播行为,超时)
属性:
1.propagation:事物的传播行为,他使用的Propagation类的枚举值,例如Propagation.REQUIRED
2.isolation:表示隔离级别,使用isolation类的枚举值,表示隔离级别,默认isolation.DEFAULT
3.readOnly:boolean类型的值,表示数据库操作是不是只读的。默认是false,默认不是只读,
4.timeout:事物超时,默认是1,整数值,单位是秒,例如timeout=20
5.rollbackFor:事物回滚的异常类列表,他的值是一个数组,每个值是异常类型的class,
6.rollbackForClassName:表示回滚的异常类列表,他的值是异常名称,是string类型的值,
7.noRollbackFor:不需要回滚的异常列表,是class类型的
8.noRollbackForClassName:不需要回滚的异常类列表,是string类型的值,

注解的使用步骤:
1.在spring的配置文件,声明事物内容
声明事物管理器,说明使用哪个事物管理器对象
声明使用注解管理事务,开启事物注解驱动

2.在类的源代码中加入@Transaction

事物的控制模式,
1.编程式,在代码中编程控制事物,
2.声明事物,不用编码

spring配置文件代码

<?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: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
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--加载外部文件-->
    <context:property-placeholder location="jdbc.properties"/>

    <!--声明数据源DateSource-->
    <bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <property name="url" value="${jdbc.url}"/>
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="username" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--声明sqlessionFactory,在这个类的内部,创建sqlSessionFactory-->
    <bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean" >
        <!-- 指定数据源-->
        <property name="dataSource" ref="myDataSource"/>
        <!--指定mybatis主配置文件
            resource可以直接使用 value属性赋值
        -->
        <property name="configLocation" value="classpath:mybatis.xml"/>
    </bean>
    <!--声明扫描器-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--指定sqlSession-->
        <property name="sqlSessionFactoryBeanName" value="factory"/>
        <!--指定基本包,dao接口所在的包名-->
        <property name="basePackage" value="com.dao"/>
     </bean>

     <!--声明service-->
    <bean id="buyService" class="com.service.impl.BuyGoodsServiceImpl">
        <property name="goodsDao" ref="goodsDao"/>
        <property name="saleDao" ref="saleDao"/>
    </bean>

    <!--声明事物的控制-->
    <!--声明事物管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <!--指定数据源-->
        <property name="dataSource" ref="myDataSource"/>
    </bean>
    <!--开启事物注解驱动:告诉框架使用注解管理事务
        transaction-manager:指定事务管理器的id
    -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

实现类代码

package com.service.impl;

import com.dao.GoodsDao;
import com.dao.SaleDao;
import com.entity.Goods;
import com.entity.Sale;
import com.exception.NotEnougthException;
import com.service.BuyGoodsService;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

public class BuyGoodsServiceImpl implements BuyGoodsService {

    private SaleDao saleDao;
    private GoodsDao goodsDao;

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

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

    /**
     *   @Transactional 放在public方法的上面,表示方法有事物功能
     *
     */

    /*   第一种设置方式
    @Transactional(propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            readOnly = false,
            timeout = 20,
            rollbackFor = {NullPointerException.class,NotEnougthException.class})
    */
    /*   第二种设置方式
    @Transactional(
            propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            readOnly = false,timeout = 20
    )
    解释 rollbackFor 的使用:
    1.框架首先检查方法抛出的异常是不是在rollbackfor数组中,如果在一定回滚,
    2.如果方法抛出的异常不在rollbackfor数组中,,框架会继续检查抛出的异常是不是runtimeexception
    如果是runtimeException,一定回滚,

    例如 抛出sqlexception,IOexception
    rollbackfor={sqlexception.class,IOexception.class}
    */
    /**
     * 第三种方式使用默认方式
     * required,发生运行时异常回滚
     * */
    @Transactional
    @Override
    public void buy(Integer goodsId, Integer num) {
        System.out.println("***buy方法的开始***");
        //生成销售记录
        Sale sale=new Sale();
        sale.setGid(goodsId);
        sale.setNum(num);
        saleDao.insertSale(sale);
        //查询商品
        Goods goods=goodsDao.selectById(goodsId);
        if (goods==null){
            throw  new NullPointerException(goodsId+",商品不存在");
        }else if (goods.getAmount()<num){
            throw new NotEnougthException(goodsId+",库存不足");
        }

        //更新库存
        Goods buygoods=new Goods();
        buygoods.setId(goodsId);
        buygoods.setAmount(num);
        goodsDao.updateGoods(buygoods);

        System.out.println("***buy方法的结束***");
    }
}

@Transactional 使用的特点
1.spring框架自己提供的事物控制
2.适合中小型项目
3.使用方便,效率高

使用AspectJ框架在spring的配置文件中,声明事物控制

使用aspectJ的AOP,声明事物控制叫做声明事物

使用步骤;
1.在pom.xml加入spring-aspects的依赖
2.在spring的配置文件声明事物的内容
(1)声明事务管理器
(2)声明业务方法需要的事物属性
(3)声明切入点表达式

该内容基本不需要大的改变,使用时注意细节就行

 <!--声明事物,不写代码-->
    <!--1.声明事物管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="myDataSource"/>
    </bean>
    <!--2.声明业务方法的配置属性(隔离级别,传播行为,超时)
    id:给业务方法配置事物代码起个名称,唯一值
    transaction-manager:事务管理器的id
    -->
    <tx:advice id="serviceAdvice" transaction-manager="transactionManager">
        <!--给具体事务方法增加事物说明
            name:业务方法名称,配置name的值,1.业务方法的名称,2.带有部分通配符的方法名称,3.使用*
            propagation:指定传播行为的值
            isolation    隔离级别
            read-only    是否只读,默认false
            timeout     超时时间
            rollbackfor 指定的回滚的异常类列表,使用的异常全限定名称
        -->

        <tx:attributes>

            <tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT" read-only="false" timeout="20"/>
            <tx:method name="add*" propagation="REQUIRED" isolation="DEFAULT" timeout="20" read-only="false"/>
            <!--以上方法以外的都-->
            <tx:method name="*" propagation="REQUIRED" timeout="20" read-only="false" isolation="DEFAULT"/>
        </tx:attributes>
    </tx:advice>

    <!--声明切入点表达式,表示哪些类和类中的方法参与事物-->
    <aop:config>
        <!--声明切入点表达式
        expression:切入点表达式,表示哪些类和类中哪些方法要参与事物
        id:切入点表达式的名称,唯一值

        expression怎么写
        -->
        <aop:pointcut id="servicepointcut" expression="execution(* *..service..*.*(..))"/>
        <!--关联切入点表达式和事物通知-->
        <aop:advisor advice-ref="serviceAdvice" pointcut-ref="servicepointcut"/>
     </aop:config>

声明式事物优缺点:
1.缺点:难以理解,配置复杂
2.代码和事物的配置是分开的,控制事物源代码不用修改,能快速地了解该项目的事物,适合大型项目

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值