乐趣区

Spring事务之REQUIRESNEW

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

<bean id="propagationUtil" class="com.wanbo.service.order.common.PropagationUtil$" />

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")
      )
    }
  }

}
退出移动版