上一章咱们简单的介绍了swagger相关的实现,毕竟我都是直接贴代码了,确实也是挺简单的,哈哈哈。 这一章咱们主要介绍在springboot中的事务控制。java
本项目的GitHub:https://github.com/pc859107393/Go2SpringBoot.gitgit
有兴趣交流springboot进行快速开发的同窗能够加一下下面的企鹅群。github
在传统的Spring项目中,咱们经典三层中主要在service层进行事务控制,常见的配置是什么呢?具体实现如图3.1所示。spring
图3.1 传统Spring项目的事务控制数据库
在传统的Spring项目中,咱们的事务控制须要考虑以下几点:express
既然咱们知道了传统的事务控制咱们须要作的事情,理解了这一点,咱们也就能够在springboot项目中推测咱们须要哪些东西。 ①. 事务控制相关依赖资源 ②. 事务管理开启 ③.事务读写规则控制 ④.事务读写的实现.springboot
在前面咱们构建项目的时候已经加入了spring-boot-starter-aop
,因此依赖资源不是问题。接着咱们须要编写代码来实现相关的规则、开启事务和实现事务。app
首先咱们能够上网查询一下springboot相关的事务,无外乎都是懒人办法直接在service方法上面添加注解@Transactional
和在入口类上面使用@EnableTransactionManagement
,这样就能在项目中指定的方法上面开启事务了。spring-boot
可是有没有一种更懒得方式呢?必定是有的,估计也是和Spring项目中相似。咱们检验的标准是什么?确定是在service对应的方法内发生异常引发回滚操做。其余的原理没必要解释太多,先上码。工具
@SpringBootApplication
@EnableWebMvc
@EnableSwagger2
@MapperScan(value = ["cn.acheng1314.base.dao"])
@Configuration
@EnableTransactionManagement
class BaseApplication : WebMvcConfigurer {
//事务类型参数
fun transactionAttributeSource(): TransactionAttributeSource {
val source = NameMatchTransactionAttributeSource()
//只读或可写事务
val readOnlyTx = RuleBasedTransactionAttribute()
readOnlyTx.isReadOnly = true
readOnlyTx.propagationBehavior = TransactionDefinition.PROPAGATION_SUPPORTS
//可写事务
val requiredTx = RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED
, Collections.singletonList(RollbackRuleAttribute(Exception::class.java)))
val txMap = HashMap<String, TransactionAttribute>()
txMap["add*"] = requiredTx
txMap["save*"] = requiredTx
txMap["insert*"] = requiredTx
txMap["update*"] = requiredTx
txMap["delete*"] = requiredTx
txMap["get*"] = readOnlyTx
txMap["query*"] = readOnlyTx
txMap["find*"] = readOnlyTx
source.setNameMap(txMap)
return source
}
/*事务拦截器*/
@Bean(value = ["txInterceptor"])
fun getTransactionInterceptor(tx: PlatformTransactionManager): TransactionInterceptor {
return TransactionInterceptor(tx, transactionAttributeSource())
}
/**切面拦截规则 参数会自动从容器中注入 */
@Bean
fun pointcutAdvisor(txInterceptor: TransactionInterceptor): AspectJExpressionPointcutAdvisor {
val pointcutAdvisor = AspectJExpressionPointcutAdvisor()
pointcutAdvisor.advice = txInterceptor
pointcutAdvisor.expression = "execution (* cn.acheng1314.base.service.*ServiceImpl.*(..))"
return pointcutAdvisor
}
//省略其余代码
}
复制代码
在上面的事务规则参数中咱们设置了两边倒事务(readOnlyTx,使用了TransactionDefinition.PROPAGATION_SUPPORTS
设置为两边倒事务)和可写入事务(requiredTx)。接着咱们在UserServiceImpl中写一个发生异常的方法,测试是否可以产生事务回滚,代码片断以下:
// @Transactional
@Throws(Exception::class)
fun addUser() {
val user = User()
user.duty = "aaa"
user.loginName = "aaa"
user.name = "aaa"
user.password = "aaa"
user.createDate = Date()
baseMapper.insert(user)
throw Exception("测试事务")
}
复制代码
咱们来一点点代码进行单元测试,以下:
@RunWith(SpringJUnit4ClassRunner::class)
@SpringBootTest(classes = [BaseApplication::class])
class UserServiceImplTest {
@Autowired
private lateinit var userService: UserServiceImpl
@Test
fun addUserTest() {
userService.addUser()
}
}
复制代码
最后运行测试代码后,咱们能够发如今数据库中并无aaa这个用户信息存在,因此咱们事务控制成功了。具体效果不用上图了,你们都能在各自的数据库工具中看到。