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("异常数据")) } ) } } }