NC内嵌事务

概述

在对NC进行客户化开发时,代码中有一段业务逻辑需要需要在出错时进行部分回滚。根据能查询到的资料,并没有发现NC有直接支持内嵌事务的API。查看源码后,机缘巧合发现有关于保存点的代码,解决了问题。

过程

与Spring的AOP类似,NC中通过NCLocator调用接口,也是以代理的方式间接执行具体方法,中间会穿插一些系统逻辑。比如 nc.bs.framework.ejb.CMTEJBServiceHandler 的invoke方法,会判断调用的Method名称,如果是以_RequiresNew结尾,就开启一个新事务。下面简单介绍一下NC事务的配置。

接口的类型

使用NCLocator调用的接口,需要先行在对应模块的UPM文件中配置。其中,接口的属性tx代表事务类型,有3种:

  • NONE:不开启事务
  • BMT(Bean-Managed Transaction):由Bean直接对事务进行提交操作,不常用
  • CMT(Container-Managed Transaction):由Container对事务进行控制

注意点

由CMT管理的任何方法,只要在执行过程中,抛出了异常,即使在NCLocator外部被捕获了,抛出异常时给容器事务打上的rollback标记也不会消失,所以在容器执行结束的时候,整个事务还是会被回滚。

源码追踪

在 nc.itf.framework.ejb.CMTProxy_Local 中,NC对被调用的方法进行了代理,在方法执行前后执行事务控制。继续深入,发现事务是由 uap.mw.trans.UAPTransactionManager 开启的,该类中实现了事务的启动、回滚和提交等操作。根据传入的 methodId ,启动不同类型的事务。当 methodId 为11的时候,会继续使用本线程当前事务并开启一个保存点。

case 11 :
  this.createTransaction(TransactionContextType.JOINED);
  try {
    this.setCurInvokeSavePoint();
  } catch (SQLException var3) {
    throw new NotSupportedException("savePoint error!");
  }

结果

使用下述代码包裹需要使用内嵌事务的业务逻辑,手动开启内嵌事务。并在逻辑执行完毕后判断是否有异常,再决定提交还是回滚。不明白为什么NC实现了内嵌事务,却没有提供类似_RequiresNew开启新事务这样的便捷操作。可能是比较难以控制,因为业务逻辑里可能会继续使用NCLocator调用其他系统接口,这些接口很多都开启了CMT,一旦它们之中有报错,会使整个容器事务回滚,从而导致内嵌事务失效。

TransactionFactory.getTMProxy().begin(11, 11);
Exception exception = null;
try {
  // 需要执行的业务逻辑
} catch (Exception e) {
  exception = e;
  throw e;
} finally {
  TransactionFactory.getTMProxy().end(exception);
}

你可能感兴趣的:(NC内嵌事务)