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

Spring 的事务管理

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

Spring 的事务管理

//本文章参看BliBli学习总结,感谢提供视频的北京动力节点,本文章仅分享供大家参考学习,没有商业用途,谢谢!
为什么要使用事务管理?

事务是一组sql语句的集合,在开发项目时,sql语句的执行往往有多条同时执行,这是就要保证所有语句都执行正确,才能完成某个功能,即执行的语句都能成功或都失败,否则就会出现数据库数据异常,此时就需要对事务进行管理,如果sql语句集合有报错语句,执行回滚操作。

第一步:实现基本的业务功能 1、创建数据库表

数据库名:ssm

表goods

表sale

2、新建一个项目:spring-trans


3、修改pom.xml文件



  4.0.0

  com.bjpowernode
  spring-trans
  1.0-SNAPSHOT

  spring-trans
  
  http://www.example.com

  
    UTF-8
    1.8
    1.8
  

  
    
    
      junit
      junit
      4.11
      test
    
    
    
      org.springframework
      spring-context
      5.2.5.RELEASE
    
    
    
      org.springframework
      spring-tx
      5.2.5.RELEASE
    
    
      org.springframework
      spring-jdbc
      5.2.5.RELEASE
    
    
    
      org.mybatis
      mybatis
      3.5.1
    
    
    
      org.mybatis
      mybatis-spring
      1.3.1
    
    
    
      mysql
      mysql-connector-java
      5.1.9
    
    
    
      com.alibaba
      druid
      1.1.12
    
  

  
    
    
      
        src/main/java
        
          ***.xml
        
        false
      
    
    
    
      
        maven-compiler-plugin
        3.1
        
          1.8
          1.8
        
      
    
  


4、java/com.bjpowernode.domain包,创建实体类

Goods.java

package com.bjpowernode.domain;

public class Goods {
    private Integer id;
    private String name;
    private Integer amount;
    private float price;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAmount() {
        return amount;
    }

    public void setAmount(Integer amount) {
        this.amount = amount;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }
}

Sale.java

package com.bjpowernode.domain;

public class Sale {
    private Integer id;
    private Integer gid;
    private Integer nums;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getGid() {
        return gid;
    }

    public void setGid(Integer gid) {
        this.gid = gid;
    }

    public Integer getNums() {
        return nums;
    }

    public void setNums(Integer nums) {
        this.nums = nums;
    }
}
5、java/com.bjpowernode.dao包中,定义接口

GoodsDao.java

package com.bjpowernode.dao;

import com.bjpowernode.domain.Goods;

public interface GoodsDao {
    int updateGoods(Goods goods);
    Goods selectGoods(Integer goodsId);
}

SaleDao.java

package com.bjpowernode.dao;


import com.bjpowernode.domain.Sale;

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

6、java/com.bjpowernode.dao包中,定义dao接口对象的sql映射文件

GoodsDao.xml




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


SaleDao.xml




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


7、java/com.bjpowernode.excep包中,定义异常类

NotEnoughException.java

package com.bjpowernode.excep;

public class NotEnoughException extends RuntimeException{
    public NotEnoughException(){
        super();
    }
    public NotEnoughException(String msg){
        super(msg);
    }
}

8、java/com.bjpowernode.service包中,定义service接口

BuyGoodsService.java

package com.bjpowernode.service;

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

9、java/com.bjpowernode.service.impl包中,定义service接口实现类

BuyGoodsServiceImpl.java

package com.bjpowernode.service.impl;

import com.bjpowernode.dao.GoodsDao;
import com.bjpowernode.dao.SaleDao;
import com.bjpowernode.domain.Goods;
import com.bjpowernode.domain.Sale;
import com.bjpowernode.excep.NotEnoughException;
import com.bjpowernode.service.BuyGoodsService;
//类定义
public class BuyGoodsServiceImpl implements BuyGoodsService {
    //Dao属性
    private GoodsDao goodsDao;
    private SaleDao saleDao;
    //buy方法
    @Override
    public void buy(Integer goodsId, Integer amount) {
        Sale sale = new Sale();
        sale.setGid(goodsId);
        sale.setNums(amount);
        saleDao.insertSale(sale);

        Goods goods = goodsDao.selectGoods(goodsId);
        if(goods==null){
            throw new NullPointerException("编号是:"+goodsId+",商品不存在");
        }
        if(goods.getAmount()
10、main下新建resources目录,标记目录为resources根,并创建以下文件

applicationContext.xml




    
    

    
    
        
        
        
        
        
        
    

    
    
        
        
        
        
    

    
    
        
        
        
        
    

    
    
        
        
    


jdbc.properties

jdbc.url=jdbc:mysql://localhost:3306/ssm
jdbc.username=root
jdbc.passwd=root
jdbc.max=30

mybatis.xml





    
    
        
        
    

    
    
        
        
    


11、test/java/com.bjpowernode包中定义测试类

MyTest.java

package com.bjpowernode;

import com.bjpowernode.service.BuyGoodsService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    @Test
    public void testBuy(){
        String configLocation ="applicationContext.xml";
        ApplicationContext ctx= new ClassPathXmlApplicationContext(configLocation);
        BuyGoodsService service = (BuyGoodsService) ctx.getBean("buyService");
        service.buy(1001,2);
    }
}

第二步:实现事务管理 第一种方法:使用spring的事务注解管理事务 1、在applicationContext.xml文件beans标签里,声明事务管理器
 
    
    
        
        
    
2、在1后边接着声明事务注解驱动
 
    
applicationContext.xml完整代码



    
    

    
    
        
        
        
        
        
        
    

    
    
        
        
        
        
    

    
    
        
        
        
        
    

    
    
        
        
    
    
    
    
        
        
    

    
    


3、在service业务实现类中,public方法上,加入事务属性@Transactional
注意:Transactional若用在方法上,只能用于public方法上。对于其他非public方法,如果加上了注解@Transactional,虽然spring不会报错,但不会将指定事务织入到该方法中。因为spring会忽略掉所有非public方法上的@Transaction注解。
	如果@Transaction注解在类上,表示该类上的所有方法均将在执行是织入事务。
@Transactional的所有可选属性有:
	propagation;isolation;readOnly;timeout;rollbackFor;rollbackForClassName;noRollbackFor;noRollbackForClassName;
@Transactional的常用属性:
	rollbackFor:指定需要回滚的异常类。类型为Class[],默认值为空数组。
		rollbackFor的处理逻辑:spring框架会首先检查方法抛出的异常是不是在rollbackFor属性值中:
			1、如果抛出的异常在rollbackFor列表中,不管什么类型的异常,一定回滚
			2、如果抛出的异常不在rollbackFor列表中,spring会判断异常是不是RuntimeException(运行时异常),如果是!就一定回滚。也就是说,rollbackFor没有值或不写时,默认抛出RuntimeException异常。
@Transactional使用举例:
	1、不带任何属性:所有属性为默认值
	2、带属性举例:
		@Transactional(propagation = Propagation.REQUIRED,rollbackFor = {NotEnoughException.class,NullPointerException.class})
注意:Exception分为两类:
	运行时异常:RuntimeException及其子类,即只有在运行时才出现的异常。例如:NULLPointerException,ArrayIndexOutOfBoundsException;
	受查异常:也叫编译时异常,RuntimeException及其子类以外的其他异常,即在代码编写时要求必须捕获或抛出的异常,若不处理,则无法通过编译。例如:SQLException,ClassNotFoundException,IOException;

service/impl/BuyGoodsService.Impljava

package com.bjpowernode.service.impl;

import com.bjpowernode.dao.GoodsDao;
import com.bjpowernode.dao.SaleDao;
import com.bjpowernode.domain.Goods;
import com.bjpowernode.domain.Sale;
import com.bjpowernode.excep.NotEnoughException;
import com.bjpowernode.service.BuyGoodsService;
import org.springframework.transaction.annotation.Transactional;

import java.beans.Transient;

//类定义
public class BuyGoodsServiceImpl implements BuyGoodsService {
    //Dao属性
    private GoodsDao goodsDao;
    private SaleDao saleDao;
    //buy方法
    @Transactional
    @Override
    public void buy(Integer goodsId, Integer amount) {
        Sale sale = new Sale();
        sale.setGid(goodsId);
        sale.setNums(amount);
        saleDao.insertSale(sale);

        Goods goods = goodsDao.selectGoods(goodsId);
        if(goods==null){
            throw new NullPointerException("编号是:"+goodsId+",商品不存在");
        }
        if(goods.getAmount()
4、测试方法

MyTest.java

package com.bjpowernode;

import com.bjpowernode.service.BuyGoodsService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
	//实现业务基本功能测试
    @Test
    public void testBuy(){
        String configLocation ="applicationContext.xml";
        ApplicationContext ctx= new ClassPathXmlApplicationContext(configLocation);
        BuyGoodsService service = (BuyGoodsService) ctx.getBean("buyService");
        service.buy(1001,2);
    }
    //spring事务注解管理事务测试
    @Test
    public void test01(){
        String config="applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        //从容器获取service
        BuyGoodsService service = (BuyGoodsService) ctx.getBean("buyService");
        //com.sun.proxy.$Proxy16 :jdk动态代理对象
        System.out.println("service是代理:"+service.getClass().getName());
        service.buy(1001,20);
    }

}
第二种方法:使用AspectJ的AOP配置管理事务

删除,或者注释掉第一种方法添加的所有代码

1、pom.xml文件中加入aspectJ的依赖
    
      org.springframework
      spring-aspects
      5.2.5.RELEASE
    
完整的pom.xml文件



  4.0.0

  com.bjpowernode
  spring-trans
  1.0-SNAPSHOT

  spring-trans
  
  http://www.example.com

  
    UTF-8
    1.8
    1.8
  

  
    
    
      junit
      junit
      4.11
      test
    
    
    
      org.springframework
      spring-context
      5.2.5.RELEASE
    
    
    
      org.springframework
      spring-tx
      5.2.5.RELEASE
    
    
      org.springframework
      spring-jdbc
      5.2.5.RELEASE
    
    
    
      org.mybatis
      mybatis
      3.5.1
    
    
    
      org.mybatis
      mybatis-spring
      1.3.1
    
    
    
      mysql
      mysql-connector-java
      5.1.9
    
    
    
      com.alibaba
      druid
      1.1.12
    
    
    
      org.springframework
      spring-aspects
      5.2.5.RELEASE
    
  

  
    
    
      
        src/main/java
        
          ***.xml
        
        false
      
    
    
    
      
        maven-compiler-plugin
        3.1
        
          1.8
          1.8
        
      
    
  


2、applicationContext.xml文件中,声明事务管理器
  
    
    
        
    
3、applicationContext.xml文件中,配置事务通知
 
    
        
        
            
            

            
            
            
            
            
            
            
            
        
    
4、applicationContext.xml文件中配置aop
 
    
        
        
        
        
    
完整的applicationContext.xml文件



    
    

    
    
        
        
        
        
        
        
    

    
    
        
        
        
        
    

    
    
        
        
        
        
    

    
    
        
        
    
    
    

    
        
    
    
    
    

    
    
    
    
        
    

    
    
        
        
            
            

            
            
            
            
            
            
            
            
        
    

    
    
        
        
        
        
    

5、测试方法

MyTest.java

package com.bjpowernode;

import com.bjpowernode.service.BuyGoodsService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    //实现业务基本功能测试
    @Test
    public void testBuy(){
        String configLocation ="applicationContext.xml";
        ApplicationContext ctx= new ClassPathXmlApplicationContext(configLocation);
        BuyGoodsService service = (BuyGoodsService) ctx.getBean("buyService");
        service.buy(1001,2);
    }
    //spring事务注解管理事务测试
    @Test
    public void test01(){
        String config="applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        //从容器获取service
        BuyGoodsService service = (BuyGoodsService) ctx.getBean("buyService");
        //com.sun.proxy.$Proxy16 :jdk动态代理对象
        System.out.println("service是代理:"+service.getClass().getName());
        service.buy(1001,20);
    }
    //使用AspectJ的AOP配置管理事务测试
    @Test
    public void test02(){
        String config="applicationContext.xml";
        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);
        //从容器种获取service
        BuyGoodsService service =(BuyGoodsService) ctx.getBean("buyService");
        //com.sun.proxy.$Proxy12
        System.out.println("service是代理:"+service.getClass().getName());
        //调用方法
        service.buy(1001,100);
    }

}

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

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

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