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