Java每日面试题(事务相关)(day5)

目录

什么是事务?


事务是一个操作序列,要么全部执行成功,要么全部执行失败。事务有四个重要特性,称为 ACID 特性:

  • Atomicity(原子性):事务中的所有操作要么全部完成,要么全部不完成。
  • Consistency(一致性):事务完成后,数据要处于一致的状态。
  • Isolation(隔离性):一个事务的执行不能被其他事务干扰。
  • Durability(持久性):事务完成后,数据应该永久保存

spring事务的实现方式


事务就是一系列的操作原子执行。Spring事务机制主要包括声明式事务和编程式事务。

  • 编程式事务:通过编程的方式管理事务,这种方式带来了很大的灵活性,但很难维护。
  • 声明式事务 :将事务管理代码从业务方法中分离出来,通过aop进行封装。Spring声明式事务使得我们无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。使用 @Transactional 注解开启声明式事务。

事务失效的8种情况


  1. public修饰的方法
    @Transactional 注解只能在在public修饰的方法下使用。

  2. 自调用(Self-Invocation)

    自调用指的是一个类的方法在调用同一个类的另一个方法,事务管理会失效。

    类内部非直接访问带注解标记的方法 B,而是通过类普通方法 A,然后由 A 调用 B。 自己调用自己

    java 复制代码
    @Service
    public class Demo {
    
      public void A() {
    
        this.B();
      }
      
      @Transactional
      public void B() {
         ......
      }
    }

解决方法:

解决方法是将这些方法拆分到不同的类中,或者通过 Spring 的代理来调用这些方法。

在该Service类中使用AopContext.currentProxy()获取代理对象

java 复制代码
@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)
@EnableTransactionManagement
public class App {

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

}

通过调用代理对象中被增强过的方法实现事务

java 复制代码
((ServiceA)AopContext.currentProxy()).doSave(user);

或者

  1. 数据库不支持事务

    MySQL中,MyISAM引擎不支持事物,InnoDB 支持事物

  2. 异常类型不匹配
    @Transactional 注解默认只管理运行时异常(如RuntimeException及其子类)和错误(如Error)。

    当抛出未被捕获的运行时异常时,Spring 会触发事务回滚操作,将之前的操作撤销;对于受检异常(即必须被捕获或声明抛出的异常,例如IOException,SQLException等),除非你明确配置事务管理器去处理它们,否则事务不会回滚。

    可以通过 rollbackFornoRollbackFor 属性来指定需要回滚或不需要回滚的异常类型。

  3. 传播属性设置问题

    propagation属性错误
    @Transactional 默认的事务传播机制是:REQUIRED,若指定成了NOT_SUPPORTEDNEVER事务传播机制,则事物不生效,如:

    java 复制代码
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
  4. 捕获异常未抛出

    java 复制代码
    //自己消化掉了异常
    @Transactional
    public void A(){
    	try{
    	   ......
    	}catch(Exception e){
    	   // 未抛异常
    	}
    }
  5. Bean没有纳入Spring IOC容器管理

    使用spring事务的前提是:对象要被spring管理,需要创建bean实例。如果类没有加@Controller、@Service、@Component、@Repository等注解,即该类没有交给spring去管理,那么它的方法也不会生成事务。

    java 复制代码
    // 注释调@Component,该类没被Spring管理,事物也是不生效的
    public class Demo {
      
      @Transactional(rollbackFor = Exception.class)
      public void A() {
         ......
      }
    }
  6. 事务方法内启动新线程进行异步操作

    主线程没有拿到子线程的异常,所以代理类以为正常执行了

    java 复制代码
     @Transactional()
        public int transfer2(String from,String to, int money){
            accountDao.decrMoney(from,money);
    
            new Thread(()->{
                int c = 5/0;
                accountDao.addMoney(to,money);
            }).start();
            return 1;
        }
相关推荐
一点媛艺1 小时前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风1 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
奋斗的小花生2 小时前
c++ 多态性
开发语言·c++
魔道不误砍柴功2 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2342 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
Nu11PointerException2 小时前
JAVA笔记 | ResponseBodyEmitter等异步流式接口快速学习
笔记·学习
闲晨2 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
老猿讲编程2 小时前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk3 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*3 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go