spring - 事务管理源码分析

spring - 事务管理源码分析

1,关于事务的案例分析

下单成功 --> 修改库存
在这里插入图片描述
提出问题:
1,实现原理?
aop -》 动态代理
2,spring如何控制事务的的提交与回滚?
3,有哪些不同类型的事务传播属性?分别有什么效果?

2,spring事务管理的实现原理

3,spring事务管理的传播属性

在这里插入图片描述

事务挂起是什么意思?

在这里插入图片描述

新建事务 与 嵌套事务的区别?

新建事务:使用 @transactional 时传播属性设置为 required_new 时
如果不想让内部事务影响外部事务,需要在内部事务的方法里面进行 try。。catch。。,但是 try。。catch。。后如果异常发生在SQL语句之后,内部事务是不会回滚的。

嵌套事务:

MySQL的事务
在这里插入图片描述
嵌套事务的内部事务是不影响外部事务的,当内部事务出现异常时,会把整个保存点抹除;但是嵌套事务的外部事务会影响内部事务,当外部事务发生异常时整个事务下的SQL都会回滚。
在这里插入图片描述

4,通过源码理解事务管理的存在

org.springframework.aop.framework.CglibAopProxy
retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();

org.springframework.aop.framework.ReflectiveMethodInvocation
proceed(){
	// ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
	org.springframework.transaction.interceptor.TransactionInterceptor
	invoke(){
		invokeWithinTransaction(){
			org.springframework.transaction.interceptor.TransactionAspectSupport
				invokeWithinTransaction(){
					createTransactionIfNecessary(){
					// 父类 org.springframework.transaction.support.AbstractPlatformTransactionManager
						tm.getTransaction(){ 
							// 判断不同的传播属性
							
							// 执行正在的业务方法
							invocation.proceedWithInvocation()
						}
					}
				}
		}
	}
}

5,事务的总结

在这里插入图片描述

代码示例:
依赖:

<dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
	<version>2.0.0</version>
</dependency>

entity:

package com.test.spring.transaction.entity;

import lombok.Data;

@Data
public class Order {
    private Integer orderId;
    private Integer productId;
    private String customer;
    private Integer number;
    private Integer status;
}

mapper

package com.test.spring.transaction.mapper;

import com.test.spring.transaction.entity.Order;
import org.apache.ibatis.annotations.Insert;
import org.springframework.stereotype.Repository;

@Repository
public interface OrderMapper {
    int inster(Order order);
}
package com.test.spring.transaction.mapper;
import com.test.spring.transaction.entity.Order;
import org.springframework.stereotype.Repository;

@Repository
public interface ProductMapper {
    int update(Order order);
}

service

package com.test.spring.transaction.service;

import com.test.spring.transaction.entity.Order;

public interface IOrderService {
    int shopping(Order order);
}
package com.test.spring.transaction.service;
import com.test.spring.transaction.entity.Order;

public interface IProductService {
    int updateProduct(Order order);
}
package com.test.spring.transaction.service;

import com.test.spring.transaction.entity.Order;
import com.test.spring.transaction.mapper.OrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class OrderServiceImpl implements IOrderService{

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private IProductService productService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int shopping(Order order) {
        System.out.println("==================>进入shopping方法");
        // 下单,插入数据到order表中
        int row = orderMapper.inster(order);
        // 更新库存数量
        productService.updateProduct(order);
        System.out.println("==================>完成shopping方法");
        return row;
    }
}
package com.example.mytransaction.service;
import com.example.mytransaction.entity.Order;
import com.example.mytransaction.mapper.ProductMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ProductServiceImpl implements IProductService {
    @Autowired
    private ProductMapper productMapper;

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public int updateProduct(Order order) {
        System.out.println("==================>进入updateProduct方法");
        int row = 0;
        try {
            // 更新库存数量
            row = productMapper.update(order);
            // 在SQL语句执行之后报错时,不会回滚。
            int i = 1/0;
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("==================>完成updateProduct方法");
        return row;
    }
}

test 类

package com.test;
import com.test.spring.transaction.service.IOrderService;
import com.test.spring.transaction.entity.Order;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class TransactionTest {

    @Autowired
    private IOrderService orderService;

    @Test
    public void test(){
        System.out.println("==================>进入test方法");
        Order order = new Order();
        order.setProductId(100);
        order.setCustomer("张三");
        order.setNumber(1);
        // 调用shopping方法之前,调用了springaop 事务管理器去完成事务的初始化
        orderService.shopping(order);
        System.out.println("==================>进入test方法");
    }
}

数据库表结构

CREATE TABLE `temp_order` (
  `product_Id` int(11) DEFAULT NULL COMMENT '产品类型编号',
  `customer` varchar(255) DEFAULT NULL COMMENT '购买用户',
  `number` int(11) DEFAULT NULL COMMENT '购买数量',
  `order_id` int(11) NOT NULL AUTO_INCREMENT,
  `status` int(11) DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `temp_product` (
  `product_id` int(11) NOT NULL,
  `product_name` varchar(255) DEFAULT NULL,
  `product_count` int(11) DEFAULT NULL,
  PRIMARY KEY (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

配置文件

server:
  port: 8080

spring:
  datasource:
    username: cNkTl4FnJuGl3AXMOsxnW81YKyVZEMl7
    password: cNkTl4FnJuGl3AXMOsxnW81YKyVZEMl7
    url: jdbc:mysql://10.5.6.129:3306/contract_manage?useUnicode=true&amp;characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
    driver-class-name: com.mysql.jdbc.Driver

mybatis:
  mapper-locations: classpath:mapping/*Mapper.xml

启动类上添加

@MapperScan("com.example.mytransaction.mapper")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值