RequiresNewPropagation
: 開啓獨立的新事務mysql
/** * 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
: 工具Beanspring
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
: 測試類sql
/** * 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 { // 1-4成功插入數據庫, 5失敗回滾, 後續再也不執行 @Test def requiresNewTest(): Unit = { 1.to(9).foreach { PropagationUtil.requiresNew(_)( id => mysqlData.executeUpdate(sql"insert into test set id = $id") if (id % 5 == 0) { Assert.assert(assertion = false, OrderException.bizFault("異常數據")) } ) } } // 10,15插入失敗, 但異常被捕獲, 不影響其餘事務, 11-14,16-19成功插入 @Test def requiresNewWithTryTest(): Unit = { 10.to(19).foreach { PropagationUtil.requiresNewWithTry(_)( id => mysqlData.executeUpdate(sql"insert into test set id = $id") if (id % 5 == 0) { Assert.assert(assertion = false, OrderException.bizFault("異常數據")) } ) } } }