• Micronaut事务管理


    1 Micronaut事务管理

    1.1 事务传播机制

    1.1.1 REQUIRED

    Micronaut事务的默认传播机制。

    如果当前存在事务,加入当前事务,否则开启一个新的事务。

    1.1.2 SUPPORTS

    如果当前存在事务,加入当前事务,否则不开事务。

    1.1.3 MANDATORY

    当前必须存在事务,加入这个事务,否则抛出异常。

    1.1.4 REQUIRES_NEW

    创建一个新事务,如果已经存在事务,挂起已经存在的事务,先把本事务执行完,然后恢复挂起的外层事务。

    提问:

    • 如果REQUIRES_NEW开启的内层事务发生回滚,外层事务会继续执行还是回滚? 答:如果回滚是异常造成的,且外层没有捕获异常,外层也会回滚,但如果外层catch了内层的异常,则会执行完。

    1.1.5 NOT_SUPPORTED

    不创建事务,如果已经存在事务,挂起已经存在的事务,先把本事务执行完,然后恢复挂起的外层事务。

    1.1.6 NEVER

    不创建事务,如果已经存在事务,抛出异常。

    1.1.7 调用带事务的存储过程

    @Transactional(rollbackOn = Exception.class)
    public void functionTRX(int tradeId, int flag) {
       dslContext.update(A)
          .set(A.a, 1)
          .where(A.id.eq(tradeId))
          .execute(); // (1)
    
       dslContext.fetch("CALL SP_WITH_TRANSACTION(?)", tradeId); // (2)
    
       dslContext.insertInto(B, B.b1, B.b2).values(1,2).execute(); // (3)
    }
    

    提问:

    • (2)中ROLLBACK,(1)会被回滚吗?
      • 答:不会,因为存储过程中的事务开启时,把(1)提交了。
    • (3)发生异常,哪些语句被回滚了?
      • 答:只有(3)。
    • 所以上述方法的事务是怎样被执行的?
      • (1)事务执行,(2)开启事务时(1)被提交,(2)提交后新事务执行(3)

    1.2 只读事务

    在MySQL中,可以用START TRANSACTION READ ONLY开启一个只读事务。

    在该事务中如果有对数据库的修改操作(InnoDB, MyISAM, 或其它类型的数据库表),那么将会产生一个错误,并且事务会继续以只读事务进行。

    可以对查询加S锁,但加X锁也会报错。

    但是在只读事务中,你可以对session级别的临时表进行操作,这是因为这些修改操作和加锁操作对其它事务是不可见的。

    只读事务在RR隔离级别下可以保证可重复读,但它的创建速度更快,因为只读事务不需要分配事务ID,也无需为其做回滚的准备。

    1.3 事务的开启方式

    在Micronaut中,执行SQL时必须显式地开启事务,因为Micronaut在开启事务时获取数据库连接,如果不开启事务,则无法拿到数据库连接。

    1.3.1 声明式

    1. 写事务
      @Transactional(value = Transactional.TxType.MANDATORY, rollbackOn = Exception.class)
      public void functionTRX(int tradeId, int flag) {
         // ...
      }
      

      提问:rollbackOn = Exception.class的意义是什么? 答:如果不加这个配置,则事务只会在RuntimeException发生时回滚,如果发生了其它Exception,会出现事务未结束。

    2. 只读事务
      @ReadOnly
      public void functionTRX(int tradeId, int flag) {
         // ...
      }
      

    1.3.2 函数式

    dslContext.transaction(configuration -> {
       DSLContext dslContext = DSL.using(configuration);
       // ...
    });
    
    var result= dslContext.transactionResult(configuration -> {
       DSLContext dslContext = DSL.using(configuration);
       return ...;
    });
    

    1.3.3 手动开启

    @Inject
    private SynchronousTransactionManager<Connection> trxMgr;
    
    void functionTRX() {
        TransactionStatus<Connection> trx = trxMgr.getTransaction(TransactionDefinition.READ_ONLY);
        try{    
        trxMgr.commit(trx);
        } catch (Exception e) {
        trxMgr.rollback(trx);
        }
    }
    
  • 相关阅读:
    RHEL5.8配置开机自动挂载磁盘
    RHEL5.8配置NFS服务
    Linux环境下Oracle数据库启动停止命令
    使用的组件:Layui
    使用的组件:Jcrop
    使用的组件:ckeditor
    使用的组件:Web Uploader
    WebSphere试用过期问题处理
    webpack学习笔记(一)
    如何用node命令和webpack命令传递参数 转载
  • 原文地址:https://www.cnblogs.com/wjhmrc/p/15708689.html
Copyright © 2020-2023  润新知