java事务不生效场景_导致spring事务失效的几种场景

本文详细介绍了Spring事务管理中可能出现的7种失效场景,包括未启用事务管理功能、非public方法、未配置事务管理器、自身调用问题、异常类型错误、异常被捕获以及业务和事务代码不在同一线程。对于每种场景,都提供了相应的解决策略和代码示例,帮助读者理解并避免这些问题。
摘要由CSDN通过智能技术生成

1.事务失效的7种情况

1)未启用spring事务管理功能

2)方法不是public类型的

3)数据源未配置事务管理器

4)自身调用问题

5)异常类型错误

6)异常被捕获

7)业务和spring事务代码必须在一个线程中

1.1未启用spring事务管理功能

@EnableTransactionManagement 注解用于启用spring事务自动管理功能

如果引入了autoconfigure,TransactionAutoConfiguration.class会自动启用事务管理功能

1.2方法不是public类型

@Transactional 注解可以用到类上、接口上和public方法上,如果是非public方法,事务将不会生效,主要是spring代理机制导致

1.3数据源未配置事务管理器

spring是通过事务管理器来管理事务的,一定要配置事务管理器

@BeanpublicPlatformTransactionManager transactionManager(DataSource dataSource) {

return newDataSourceTransactionManager(dataSource);}

如果引入了autoconfigure,DataSourceTransactionManagerAutoConfiguration.class会自动创建事务管理器

1.4自身调用问题

spring是通过aop的方式实现的事务管理,为每个需要事务管理的bean创建代理对象, 然后通过代理对象拦截了目标方法的执行,在方法前后添加了事务的功能,所以必须通过代理对象调用目标方法的时候,事务才会起效。

@Servicepublic classTransactionDemoService {

public voidm1(){

this.m2();;}

@Transactional(rollbackFor= Exception.class)

public voidm2(){

//db操作}

}

以上代码中,调用m1方法,m2方法中的事务是不会生效的。因为m1中调用m2是通过this调用的,不是通过代理对象。 this.m2()不会被拦截,所以事务是无效的,如果外部直接调用通过TransactionDemoService这个bean来调用m2方法,事务是有效的,上面代码可以做一下调整,如下,在TransactionDemoService中注入了自己,此时m1中的m2事务是生效的 。

@Servicepublic classTransactionDemoService {

@AutowiredprivateTransactionDemoService self;

public voidm1(){

self.m2();;}

@Transactional(rollbackFor= Exception.class)

public voidm2(){

//db操作}

}

或者,使用AopContext也能解决这个问题,如下:

@Servicepublic classTransactionDemoService {

public voidm1(){

((TransactionDemoService)AopContext.currentProxy()).m2();}

@Transactional(rollbackFor= Exception.class)

public voidm2(){

//db操作}

}

注意,当使用AopContext时, 需要使用@EnableAspectJAutoProxy(exposeProxy = true)来暴露AOP的Proxy对象才行,否则会报异常。

1.5异常类型错误

spring的事务回滚机制为,对代理的方法进行try catch 当捕获到有指定的异常时,spring自动对事务进行回滚。但是, 并不是任何异常情况下,spring都会回滚事务,默认情况下,RuntimeException和Error的情况下,spring事务才会回滚。

同时,也可以自定义回滚得异常类型:

@Transactional(rollbackFor= AccessException.class)

public voidm2(){

//db操作}

1.6异常被捕获

当业务代码抛出异常,spring感知到异常的时候,才会进行回滚,如果在业务方法里面捕获了异常,spring无法感知到异常,就不会进行回滚,如下:

@Transactional(rollbackFor= Exception.class)

public voidm2(){

try{

//db操作}catch(Exception e){

logger.error("方法执行出现异常",e);}

}

1.7业务和spring事务代码必须在一个线程中

spring事务实现中使用了ThreadLocal,ThreadLocal可以实现同一个线程中数据共享,必须是同一个线程的时候,数据才可以共享,这就要求业务代码必须和spring事务的源码执行过程必须在一个线程中,才会受spring事务的控制,比如下面代码,方法内部的子线程内部执行的事务操作将不受m1方法上spring事务的控制。

@Transactional(rollbackFor= Exception.class)

public voidm1() {

newThread() {//db操作}.start();}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 中,使用 @Transactional 注解可以实现事务管理。但是在某些情况下,@Transactional 注解可能不会生效,比如注解在事务类的内部方法上。 这是因为 Spring AOP 默认只拦截通过 Spring 容器管理的 Bean 的方法调用,而事务类通常是使用自调用的方式,因此不会被 Spring AOP 拦截。 解决这个问题的方法是使用 AspectJ。AspectJ 是一种基于语言的 AOP 实现方式,可以在编译期或者运行期织入切面。 具体实现如下: 1. 添加 AspectJ 依赖 ```xml <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> ``` 2. 配置 Spring,启用 AspectJ 自动代理 ```xml <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" /> <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" /> <aop:aspectj-autoproxy /> ``` 3. 在事务类上添加 @Aspect 注解,并实现一个切面类 ```java @Aspect @Component public class TransactionAspect { @Autowired private PlatformTransactionManager transactionManager; @Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)") public void transactionalMethod() {} @Around("transactionalMethod()") public Object doTransaction(ProceedingJoinPoint joinPoint) throws Throwable { TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); Object result; try { result = joinPoint.proceed(); transactionManager.commit(status); } catch (Exception e) { transactionManager.rollback(status); throw e; } return result; } } ``` 这个切面类会拦截所有被 @Transactional 注解标记的方法,并使用事务管理器执行事务。 以上就是解决注解@Transactional事务类内调用不生效问题的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值