Spring事务之REQUIRES_NEW

RequiresNewPropagation: 开启独立的新事务

/**
  * Created by caojialin
  * Date: 2019-08-15 20:09
  * Description: 独立于原事务外, 重新开启一个新事务, 此事务与原事务独立互不影响
  */
@Component
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Array(classOf[Throwable]))
class RequiresNewPropagation {

  val LOGGER: Logger = LoggerFactory.getLogger(getClass)

  def invoke[A, B](req: => A)(func: => A => B): B = {
    LOGGER.debug("start a new transaction ...")
    val resp = func(req)
    LOGGER.debug("finish a new transaction .")

    resp
  }
}

PropagationUtil: 工具Bean

object PropagationUtil {
  private val LOGGER: Logger = LoggerFactory.getLogger(getClass)

  @Resource
  var requiresNewPropagation: RequiresNewPropagation = _

  /**
    * 重新开启一个事务
    * @param req
    * @param func
    * @tparam A
    * @tparam B
    * @return Assert.assert 抛出的异常 被代理 最终异常为 UndeclaredThrowableException 类型
    *         异常信息: e.getUndeclaredThrowable.getMessage
    */
  def requiresNew[A, B](req: => A)(func: => A => B): B = {
    requiresNewPropagation.invoke(req)(func)
  }

  /**
    * 异常捕获 不影响后续事务
    * @param req
    * @param func
    * @tparam A
    * @tparam B
    */
  def requiresNewWithTry[A, B](req: => A)(func: => A => B): Unit = {
    try {
      requiresNewPropagation.invoke(req)(func)
    } catch {
      case e: Throwable => LOGGER.error(s"catch exception in a requires new transaction: ", e)
    }
  }
}
注意: 由于scala的object不支持注解, 所以需要在配置文件配置bean, 以便于注入RequiresNewPropagation

PropagationUtilTest: 测试类

/**
  * Created by caojialin
  * Date: 2019-08-16 10:11
  * Description: 
  */
@RunWith(classOf[SpringJUnit4ClassRunner])
@ContextConfiguration(locations = Array("classpath:META-INF/spring/services.xml"))
@Transactional
@Rollback(false) //事物不回滚
class PropagationUtilTest {

  @Test
  def requiresNewTest(): Unit = {
    1.to(9).foreach {
      PropagationUtil.requiresNew(_)( id =>
        if (id % 5 == 0) {
          Assert.assert(assertion = false, OrderException.bizFault("异常数据"))
        } else mysqlData.executeUpdate(sql"insert into test set id = $id")
      )
    }
  }

  @Test
  def requiresNewWithTryTest(): Unit = {
    10.to(19).foreach {
      PropagationUtil.requiresNewWithTry(_)( id =>
        if (id % 5 == 0) {
          Assert.assert(assertion = false, OrderException.bizFault("异常数据"))
        } else mysqlData.executeUpdate(sql"insert into test set id = $id")
      )
    }
  }

}

你可能感兴趣的:(spring,scala)