栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring详解(四)事务

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring详解(四)事务

文章目录
  • 第5章 Spring事务
    • 1 事务的概念
    • 2 在程序中事务在哪说明
    • 3. 事务管理器
      • 3.1 不同的数据库访问技术,处理事务是不同的。
      • 3.2 Spring统一管理事务,把不同的数据库访问技术的事务处理统一起来。
    • 3.3 Spring事务管理器
      • 3.4 事务的提交和回滚的时机
      • 3.5 事务使用的AOP的环绕通知
    • 4.事务定义接口TransactionDefinition
      • 4.1隔离级别
      • 4.2 事务的超时时间
      • 4.3传播行为
        • 简单商城后台购买
    • 5.Spring框架使用注解@Transactional控制事务
      • 商城后台例子改写
    • 6. 使用Aspectj框架在spring的配置文件中,声明事务控制。(适合大型项目)
      • 6.1使用步骤:
      • 6.2 声明式事务优缺点

第5章 Spring事务 1 事务的概念

​ 什么是事务?事务是一些sql序列的集合,是多条sql语句,作为一个整体执行。

mysql执行事务
beginTransaction 开启事务
insert into student() values....
select * from student where id=1001
update school set name=xxx where id= 1005
endTransaction   事务结束。

​ 什么情况下需要使用事务?

​ 一个操作需要多条(2条或2条以上的sql)sql语句一起完成,操作才能成功。

2 在程序中事务在哪说明

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

public class AccountService{
    private AccountDao dao;
    private MoneyDao dao2;
    // 在业务service(业务类) 的public方法上面,需要说明事务。
    public void trans(String a,String b,Integer money){
        dao.updateA();
        dao.updateB();   
        dao2.insertA();
    }
    
}

public class AccountDao{
    
    public void updateA(){}
    public void updateA(){}

}

public class MoneyDao{
    
    public void insertA(){}
    public void deleteA(){}

}
3. 事务管理器 3.1 不同的数据库访问技术,处理事务是不同的。

1)使用jdbc访问数据库,事务处理。

public void updateAccount(){
    Connection conn = ...;
    conn.setAutoCommit(false);
    stat.insert();
    stat.update();
    conn.commit();
    cinn.setAutoCommit(true);
}

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

public void updateAccount(){
    SqlSession session = SqlSession.openSession(true);
    try{
        session.insert("insert into student....");
        session.update("update school ...");
        session.commit();
    }catch(Exception e){
        session.rollback();
    }
    
}
3.2 Spring统一管理事务,把不同的数据库访问技术的事务处理统一起来。

​ 使用Spring的事务管理器,管理不同的数据库访问技术的事务处理。开发人员只需要掌握spring的事务处理一个方案就可以实现使用不同数据库访问技术的事务管理。

​ 管理事务面向的是spring,有spring管理事务,做事务提交,事务回顾。

3.3 Spring事务管理器

​ Spring框架使用事务管理器对象,管理所有的事务。

​ 事务管理器接口:PlatformTransactionManager。

​ 作用 :定义了事务的操作,主要是commit(),rollback()

​ 事务管理器有很多的实现类:一种数据库的访问技术有一个实现类。由实现类具体完成事务的提交,回滚。

​ 意味着:jdbc或者mybatis 访问数据库有自己的事务管理器实现类:DateSourceTranactionManager

​ hibernate框架,他的事务管理器实现类:HibernateTransactionManager。

Spring集中,统一管理事务。

3.4 事务的提交和回滚的时机

什么时候提交事务,回滚事务?

当你的业务方法正常执行时,没有异常,事务是提交的。如果你的业务方法抛出了运行时异常,事务是回滚的。

异常的分类:

Error:是严重错误。回滚事务。

Exception:异常类,可以出来的异常情况

1)运行时异常RuntimeException和他的子类都是运行时异常,在程序执行过程中抛出的异常。常见的运行时异常:

NullPoinerException(空指针),NumberFormatException(转换异常),indexOutOfBoundException(数组越界异常),AruthmeticException(算数异常),

2)受查异常:编写java代码的时候,必须出来的异常。例如IOException , SQLException,FileNotFountException。

怎么记忆:

​ 方法中抛出了运行时异常,事务回滚,其他情况(正常执行方法,受查异常)就是提交事务。

3.5 事务使用的AOP的环绕通知

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

spring给业务方法在执行时,增加上事务的切面功能;

@Arround("execution(* 所有业务类中的方法)")
public Object myAround(ProceedingJoinPoint pjp){
    try{
        PlatformTransactionManager.beginTransaction();//使用spring的事务管理器,开启事务。
        pjp.proceed();执行目标方法 //doSome();
        PlatformTransactionManager.commit();//业务方法正常执行,提交事务。
    }catch(Exception e){
    	PlatformTransactionManager.rollback();//回滚事务
    }

}
4.事务定义接口TransactionDefinition

TransactionDefinition接口。定义了三类常量,定义了有关事务控制的属性。

事务的属性:1)隔离级别 2)传播行为 3)事务的超时

给业务方法说明事务的属性。和ACID不一样。

4.1隔离级别

​ 隔离级别:控制事务之间影响的程度。

1)DEFAULT : 采用DB默认的事务隔离级别 。 MySql 的默认为 REPEATABLE_READ; Oracle 默认为 READ_COMMITTED。

2) READ_UNCOMMITTED:读未提交。未解决任何并发问题。

3) READ_COMMITTED:读已提交。解决脏读,存在不可重复读与幻读。

4) REPEATABLE_READ:可重复读。解决脏读、不可重复读,存在幻读

5) SERIALIZABLE:串行化。不存在并发问题。

4.2 事务的超时时间

超时时间,以秒为单位。整数值。默认是-1。

超时时间:表示一个业务方法最长的执行时间,如果到达时间没有执行完毕,Spring回滚事务。

4.3传播行为

传播行为有7个值。

传播行为:业务方法在调用时,事务在方法之间的,传递和调用。

使用传播行为,标识方法有无事务

PROPAGATION_REQUIRED

PROPAGATION_REQUIRES_NEW

PROPAGATION_SUPPORTS

以上三个需要掌握的。

PROPAGATION_MANDATORY

PROPAGATION_NESTED

PROPAGATION_NEVER

PROPAGATION_NOT_SUPPORTED

1)REQUIRED:spring默认传播行为,方法在调用的时候,如果存在事务就是就是使用当前的事务,如果没有事务,则新建事务,方法在新事务中执行。

2)SUPPORTS:支持,方法有事务可以正常执行,没有事务也可以正常执行。

3)REQUIRES_NEW : 方法需要一个新事务。如果调用方法时,存在一个事务,则原来的事务暂停。直到新事务执行完毕。如果方法调用时,没有事务,则新建一个事务,在事务执行代码。

简单商城后台购买

​ Spring+mybatis 实现

readme

ch15-trans-sale:

1.新建库,表sale和goods
2.创建maven项目
3.加入gav
    spring依赖,mybatis依赖,mysql驱动。junit依赖
        mybatis-spring依赖(mybatis网站上提供的,用来spring项目中,创建mybatis对象)
        spring有关事务的依赖。

4.创建实体类 Sale,Goods
5.创建dao接口和mapper文件
    SaleDao
    GoodsDao
    两个mapper文件

6.创建mybatis主配置文件

7.创建service接口和他的实现类,实现buy的方法。

8.创建Spring的配置文件
    声明数据源
    声明SqlSessionFactoryBean
    声明dao代理的对象
    声明自定义service对象

9.测试

applicationContext.xml

    
    
    
        
        
        
    

    

        


        
    
    
        
        
    

    
        
        
     

mybatis.xml




    
    
        
    
    
    
        
    
    

    
        
    

NotEnougthException

package com.sunny.exception;

public class NotEnougthException extends RuntimeException {
    public NotEnougthException() {
        super();
    }

    public NotEnougthException(String message) {
        super(message);
    }
}

public interface GoodsDao {
    Goods selectById(Integer id);
//    参数goods 表示是本次购买的  商品id    和 购买数量。
//    id商品id : amount :本次购买的此商品数量
    int updateGoods(Goods goods);
}

public interface SaleDao {
    int insertSale(Sale sale);
}

    
    

    
        update goods set amount = amount -#{amount} where id=#{id}
    



    
    
        insert into sale(gid,num) values(#{gid},#{num})
    


public interface BuyGoodsService {
    
    void buy(Integer goodsId,Integer num);
}

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;
    }

    @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方法的完成====");
    }
}
5.Spring框架使用注解@Transactional控制事务

@Transactional注解,使用注解的属性控制事务(隔离级别,传播行为,超时)

​ 属性:

​ 1.propagation : 事务的传播行为,它使用的是Propagation类的枚举值。例如Propagation.REQUIRED

​ 2.isolation : 表示隔离级别,使用isolation类的枚举值,表示隔离级别。默认Isolation.DEFAILT

​ 3.readonly : boolean类型的值,表示数据库操作是不是只读的。默认是false

​ 4.timeout : 事务超时,默认是-1,整数值,单位是秒,例如 timeout = 20

​ 5.rollbackFor : 表示回滚的异常类列表,他的值是一个数组,每个值是异常类型的class。

​ 6.rollbackForClassName : 表示回滚的异常类列表,它的值是异常类的名称,是String类型的值。

​ 7.noRollbackFor : 不需要回滚的异常类列表。是class类型的。

​ 8.noRollbackForClassName : 不需要回滚的异常类列表,是String类型的值。

位置: 1)在业务方法的上面,是public方法的上面

​ 2)在类的上面。

注解的使用步骤:

1)在Spring的配置文件,声明事务的内容

​ 声明事务管理器,说明使用哪个事务管理器对象

​ 声明使用注解管理事务,开启事务注解驱动

2)在类的源代码中,加入@Transactional。

事务的控制模式:1.编程式,代码中编程控制事务。2.声明式事务。不用编码。

@Transactional 放在 public 方法的上面。

商城后台例子改写

spring的配置文件 加入的配置

    
        
        
     





    

        

    


    


src/main/java/com/sunny/service/impl/BuyGoodsServiceImpl.java

   @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}
     */

   **
     * @Transactional
     * 第三种方式:使用的是默认值  REQUIRED , 发生运行时异常回滚。
     * */

@Transactional
    @Override
    public void buy(Integer goodsId, Integer num) {

@Transactional使用的特点:

1.spring框架自己提供的事务控制。

2.适合中小型项目。

3.使用方便

6. 使用Aspectj框架在spring的配置文件中,声明事务控制。(适合大型项目)

使用aspectj的aop,声明事务控制叫做声明式事务

6.1使用步骤:

1.pom.xml加入 spring-aspects的依赖

	
      org.springframework
      spring-aspects
      5.2.5.RELEASE
    

2.在spring的配置文件声明事务的内容

​ 1)声明事务管理器。

​ 2)声明业务方法需要的事务属性。

​ 3)声明切入点表达式。

    
        
        
     



    
        
    


    

        

            


            
            
            


            
        
    


    

        

        
    

6.2 声明式事务优缺点

1.缺点:理解难,配置复杂。

2.优点:代码和事务配置是分开的。控制事务源代码不用修改。

​ 能快速的了解和掌控项目的全部事务。适合大型项目。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/341088.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号