Spring事务——查看事务id

今天同事遇到一个问题:在使用Spring的事务管理时,开启了一个事务,接着在内部开启了两个传播模式为嵌入(PROPAGATION_NESTED)的事务,想看下这三个事务的id是否一致,但是查了半天也没查到Spring怎么获取事务id。

这里提供两个思路,不知到对不对。

1 使用MySQL的事务id

既然Spring的事务最终还是要看MySQL,那我们不如直接去MySQL里查询事务id:

SELECT TRX_ID
FROM INFORMATION_SCHEMA.INNODB_TRX
WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();

 写到mapper.xml里

<select id="getCurrentTransactionId" resultType="string" >
    SELECT TRX_ID
    FROM INFORMATION_SCHEMA.INNODB_TRX
    WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();
</select>

 

在主事务方法上添加注解:@Transactional

在子事务方法上添加 :@Transactional(propagation = Propagation.NESTED)

在方法中调用获取事务id的方法并打印出来:

############## main transaction id is: 283244068130304.
############## sub nested transaction id is: 283244068130304.

查询数据库:

这里可能存在的问题:因为这个查询使用connection_id作为条件,还没搞明白这个连接ID怎么来的,原理还有点含糊,不建议用这种方法。

2 TransactionSynchronizationManager

使用:TransactionSynchronizationManager.getCurrentTransactionName()

获取事务名,名称是加了事务注解的方法的“包名+方法名”的全路径名称。

目前来看这种方法更靠谱。

String txName = TransactionSynchronizationManager.getCurrentTransactionName();
LogConstant.BUS.info("\n  ############## main transaction name is: {}.", txName);

查看源码,是保存了一个ThreadLocal变量:

private static final ThreadLocal<String> currentTransactionName =
			new NamedThreadLocal<String>("Current transaction name");

spring的事务管理会在开启事务时往里塞值。

测试一下:

定义事务注解:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional(rollbackFor = {Exception.class})
@Documented
public @interface RunInTransactional {
    Propagation propagation() default Propagation.REQUIRED;
}

开启外层事务:

/**
 * @Description 测试事务id
 * @Author lilong
 * @Date 2019-03-11 16:19
 */
@Service
public class TestTransactional {
    @Autowired
    private TestTransactionalPropagation testTransactionalPropagation;

    @RunInTransactional
    public void testTransactionalName() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        LogConstant.BUS.info("\n  ############ main transaction name is:{}.", txName);

        testTransactionalPropagation.testNested();
        testTransactionalPropagation.testRequired();
        testTransactionalPropagation.testRequiresNew();
    }
}

在上面方法的内部开启事务(注意在新的类文件里写下面两个方法,不要跟上面的方法在同一个类里,否则事务注解会失效):

/**
 * @Description 测试事务传播机制
 * @Author lilong
 * @Date 2019-03-11 10:13
 */
@Service
public class TestTransactionalPropagation {
    /**
     * 嵌入式事务
     */
    @RunInTransactional(propagation = Propagation.NESTED)
    public void testNested() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        LogConstant.BUS.info("\n  ############## sub testNested transaction name is: {}.", txName);
    }

    /**
     * REQUIRED
     */
    @RunInTransactional(propagation = Propagation.REQUIRED)
    public void testRequired() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        LogConstant.BUS.info("\n  ############## sub testRequired transaction name is: {}.", txName);
    }

    /**
     * REQUIRES_NEW
     */
    @RunInTransactional(propagation = Propagation.REQUIRES_NEW)
    public void testRequiresNew() {
        String txName = TransactionSynchronizationManager.getCurrentTransactionName();
        LogConstant.BUS.info("\n  ############## sub testRequiresNew transaction name is: {}.", txName);
    }
}

打印结果:

############ main transaction name is:service.impl.TestTransactional.testTransactionalName.
############## sub testNested transaction name is: service.impl.TestTransactional.testTransactionalName.
############## sub testRequired transaction name is: service.impl.TestTransactional.testTransactionalName.
############## sub testRequiresNew transaction name is: service.impl.TestTransactionalPropagation.testRequiresNew.

这个方法我这边是好的,同事那边取到的事务名是null,暂时还没搞懂原因,估摸着是spring的事务框架在启动事务时往这个ThreadLocal变量里塞值了,我这边是用注解声明的方式使用的事务,同事那边用的是编程的方式,可能还是有差别,有时间再好好研究下。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值