成都网站建设设计

将想法与焦点和您一起共享

spring事物使用示例及原理总结-创新互联

目录

渝水网站建设公司创新互联,渝水网站设计制作,有大型网站制作公司丰富经验。已为渝水成百上千家提供企业网站建设服务。企业网站搭建\成都外贸网站制作要多少钱,请找那个售后服务好的渝水做网站的公司定做!

事务示例

示例一

示例二

示例三

示例四

示例五

示例六

事务原理 

@EnableTransactionManagement

执行代理对象目标方法


事务示例 示例一

在test()方法直接调用abc()方法,并在test()方法添加@Transactional,test()和abc()方法分别会更新id=1和id=2的数据name字段,abc()方法中会抛出异常。

@Component
public class TransactionService {

    @Autowired
    private TransactionService service;

    @Resource
    private UserMapper userMapper;

    @Transactional(rollbackFor = Exception.class)
    public String test(String name, String target) throws Exception {
        User user = new User();
        user.setId(1l);
        user.setName(name);
        userMapper.updateById(user);
        abc(target);
        return "ok";
    }
    
    public void abc(String target) throws Exception {
        User user = new User();
        user.setId(2l);
        user.setName(target);
        userMapper.updateById(user);
        throw new Exception("error");
    }
    
}

使用TransactionController对外提供接口做测试

@RestController
public class TransactionController {

    @Autowired
    private TransactionService service;

    @GetMapping("testT")
    public String test(@RequestBody Mapmap) throws Exception {
        return service.test(map.get("name").toString(), map.get("target").toString());
    }

}

测试之前先看数据库的值:

执行  http://localhost:8080/testT 测试

不难看出,两条更新操作都会被回滚。

示例二

在abc()方法中添加@Transactional(rollbackFor = Exception.class)注解

@Transactional(rollbackFor = Exception.class)
    public void abc(String target) throws Exception {
        User user = new User();
        user.setId(2l);
        user.setName(target);
        userMapper.updateById(user);
        throw new Exception("error");
    }

结果还是一样,都会被回滚。因为test()方法是调用的TransactionService原始对象的abc()方法。

示例三

在TransactionService中新增TransactionService 类型的成员属性,通过@Autowired注入spring bean对象,并在test()方法中使用service属性调用abc(),其用意是调用spring创建的代理对象的abc()方法。

最终结果还是一样都会回滚,因为这个线程只会创建一个事务,同一个事务要么全部回滚,要么全部提交。

示例四

在abc()方法的注解改为@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW),其用意是同一个线程在执行test()方法时创建一个事务,在调用service.abc()方法时又会创建一个事务。

最终两个方法执行的数据库更新操作还是会回滚,因为线程在执行abc()方法后抛出的异常,在test()方法中并没有处理这个异常,所以两个事务都会回滚。

示例五

在test()方法中将service.abc()方法用try catch捕获异常。

再次执行,就会发现test()方法事务会提交,而abc()方法事务会回滚。如图,id=1的name属性修改james,id=2的name属性没有发生变化。

示例六

在test()方法中将service.abc()方法try catch捕获,并且abc()方法使用的事务和test()方法使用同一个事务,此时事务会提交还是回滚呢?还会出现和示例五中abc()方法更新操作回滚,test()方法更新操作提交的效果呢?

思考一会。。。

首先这两个方法使用的是同一个事务,故它们要么全部提交,要么全部回滚。那到底是回滚还是提交,将由跟spring事务管理器中的一个属性相关,该属性为globalRollbackOnParticipationFailure,它默认等于true,表示如果参与的事务有失败的,则标记为为回滚。如果将他设置为false,表示局部执行失败的事务,也会标记为提交。所以这个事务还是会回滚。

如果将事务管理器的globalRollbackOnParticipationFailure设置为false,那么该事务就会提交。

小结:在a()方法调用b()方法时,如果他们使用同一个事务,他们的数据库更新操作要么全部提交,要么全部回滚;如果b()方法事务传播属性为REQUIRES_NEW,表示在执行b()方法时创建新事物,此时a()方法事务的提交和回滚可以不受b()方法的事务控制。 

事务原理  @EnableTransactionManagement

spring boot启动添加@EnableTransactionManagement注解,表示开启事务功能。spring解析@EnableTransactionManagement注解流程如下图。

a、导入TransactionManagementConfigurationSelector类,执行selectImports()方法,加载AutoProxyRegistrar和ProxyTransactionManagementConfiguration类。

b、spring在解析AutoProxyRegistrar时执行registerBeanDefinitions()方法,它会将InfrastructureAdvisorAutoProxyCreator注册到spring容器中,InfrastructureAdvisorAutoProxyCreator是一个BeanPostProccessor,在其父类中实现了postProcessBeforeInstantiation()方法,在实例化前会给目标对象创建代理对象。

c、spring在解析ProxyTransactionManagementConfiguration时分别会创建3个bean对象,BeanFactoryTransactionAttributeSourceAdvisor、TransactionInterceptor和AnnotationTransactionAttributeSource,分别是advisor、advice和pointcut,advice是代理逻辑,pointcut是切入点,advisor可以理解为是advice+pointcut组成的。

执行代理对象目标方法

a、当调用被代理对象目标方法时,会进入TransactionInterceptor#invoke()方法,执行invokeWithinTransaction()方法

b、getTransaction()中创建事务对象,如果事务传播属性为REQUIRED,REQUIRES_NEW,NESTED时,执行startTransaction()开启并设置事务属性。

c、首先从事务对象中获取连接对象,将连接对象设置为不自动提交。

d、执行prepareTransactionInfo()方法创建TransactionInfo对象,并将getTransaction()返回的TransactionStatus对象设置到TransactionInfo对象,然后调用bindToThread()方法获取当前线程ThreadLocal对象中的TransactionInfo对象,将其赋值给oldTransactionInfo缓存起来,将新创建的TransactionInfo对象设置到ThreadLocal对象中去。

d、执行目标方法

f、提交或者回滚,如果目标方法执行失败,抛出异常,则会执行completeTransactionAfterThrowing()进行回滚,回滚之后执行finally块的cleanupTransactionInfo()方法,将缓存在oldTransactionInfo属性的TransactionInfo对象重新设置到当前线程的ThreadLocal对象中去;如果目标方法执行成功,则先执行cleanupTransactionInfo()方法,再执行commitTransactionAfterReturning()方法提交事务。

流程图

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


分享名称:spring事物使用示例及原理总结-创新互联
当前地址:http://chengdu.cdxwcx.cn/article/dsshdp.html