Spring事务

Spring事务,第1张

Spring事务 Spring事务 1.简介

Spring提供两种事务管理方式,分为编程式和声明式。

  • 编程式:通过编码的方式手动启用、提交或回滚事务,粒度更细,但更麻烦。
  • 声明式:通过在方法或类或接口上添加注解进行包装,无侵入地实现事务,更方便,但粒度更大。

需要注意的是,使用的数据库需要支持事务,否则事务将不起作用。如MySql的MyIsam引擎就不支持事务。

2.实例 业务代码

在下面的实例中,我要先创建申请,再创建申请处理。如果创建申请处理失败,应该回滚。这里是没加事务的。为了演示,我们先注掉第7行,模拟出错。

@Override
  public boolean saveTransaction(CertApply certApply) {
    certApply.setState(1); //初审中
    save(certApply);
    ApplyDeal applyDeal = new ApplyDeal();
    applyDeal.setState(1); //初审
    applyDeal.setApplyId(certApply.getId());
    applyDealService.save(applyDeal);
    return true;
  }
运行测试


显然出现了我们要看到的问题
接下来开始使用事务进行管理

3.解决问题 依赖(Spring)
	
		org.springframework
		spring-tx
		${spring.version}
	
开启事务管理
@SpringBootApplication
@EnableAspectJAutoProxy
@EnableTransactionManagement
@MapperScan("com.example.course_system.mapper")
public class CourseSystemApplication {

  public static void main(String[] args) {
    SpringApplication.run(CourseSystemApplication.class, args);
  }

}
方法上加上@Transaction注解
 @Override
  @Transactional
  public boolean saveTransaction(CertApply certApply) {
    certApply.setState(1); //初审中
    save(certApply);
    ApplyDeal applyDeal = new ApplyDeal();
    applyDeal.setState(1); //初审
//    applyDeal.setApplyId(certApply.getId());
    applyDealService.save(applyDeal);
    return true;
  }
测试

没有新的记录加入。结果正确!

4.SpringBoot实现声明式事务的几种方式
  1. 基于动态代理支持@Transaction。

    就是上面的那种方法。但这种方法是有局限性的。在有些情况下会失效。

    • 同一个类中,方法A实现了事务,方法B中没实现事务,B中调用A。事务失效(没有经过代理类,俗称自调用问题)
    • 数据库引擎不支持事务
    • 没有被 Spring 管理
    • 方法不是 public 的
    • 异常被吃了 (高频)异常类型错误(一定要抛出RuntimeException,或者配置识别的事务类型)
  2. 基于AspectJ编译期织入来支持@Transactional

    • 用来解决上面的方法不是public的时候动态代理失效的问题
5.基于AspectJ编译期织入来支持@Transactional

我们可以采用“编译期织入”或“类加载期织入”的方式,在运行代码前,将我们的目标类的方法增强,无需管用“动态代理”实现时的种种限制。本文就接下来就讲下,如何使用AspectJ来实现在编译期对@Transactional注解的方法进行织入。

5.1.导包
   
				org.codehaus.mojo
				aspectj-maven-plugin
				1.11
				
					
						
							org.springframework
							spring-aspects
						
					
					1.8
					1.8
					1.8
					true
				
				
					
						
							compile
						
					
				
                

5.2.配置

将@EnableTransactionManagement中的mode设置为AdviceMode.ASPECTJ(默认为AdviceMode.PROXY,也就是我们的动态代理~)

然后就可以啦。这里就不测试,用兴趣的同学可以去实验下。

6.一些补充知识 6.1Transaction注解的源码
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@documented
public @interface Transactional {

	
	@AliasFor("transactionManager")
	String value() default "";

	
	@AliasFor("value")
	String transactionManager() default "";

	
	Propagation propagation() default Propagation.REQUIRED;

	
	Isolation isolation() default Isolation.DEFAULT;

	
	int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

	
	boolean readOnly() default false;

	
	Class[] rollbackFor() default {};

	
	String[] rollbackForClassName() default {};

	
	Class[] noRollbackFor() default {};

	
	String[] noRollbackForClassName() default {};

}

参考:事务传播机制 https://blog.csdn.net/qq_35493807/article/details/105756761

Class[] noRollbackFor() default {};


String[] noRollbackForClassName() default {};

}

参考:事务传播机制 https://blog.csdn.net/qq_35493807/article/details/105756761

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5678298.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存