В прошлой главе мы кратко представили реализацию, связанную с swagger, в конце концов, я только что опубликовал код напрямую, что действительно довольно просто, хахаха. В этой главе мы в основном вводим управление транзакциями в Springboot.
GitHub для этого проекта: https://github.com/pc859107393/Go2SpringBoot.git
Учащиеся, заинтересованные в общении со springboot для быстрой разработки, могут добавить следующую группу пингвинов.
Обзор управления транзакциями
В традиционном проекте Spring мы в основном выполняем управление транзакциями на сервисном уровне в классическом трехуровневом.Какова общая конфигурация? Конкретная реализация показана на рисунке 3.1.
Рисунок 3.1 Управление транзакциями традиционного проекта Spring
В традиционном проекте Spring наш контроль транзакций должен учитывать следующие моменты:
- Включить управление транзакциями
- Различие между транзакциями только для чтения и транзакциями чтения-записи
- Настройка правил управления транзакциями Spring
- Найдите класс реализации сервисного уровня
Теперь, когда мы знаем, что нам нужно делать с традиционным контролем транзакций, и понимаем это, мы можем предположить, что нам нужно в проекте springboot. ①. Зависимые ресурсы, связанные с управлением транзакциями ②. Управление транзакциями включено ③. Управление правилами чтения и записи транзакций ④. Реализация чтения и записи транзакций.
Он был добавлен, когда мы собирали проект ранее.spring-boot-starter-aop
, поэтому ресурсы зависимостей не являются проблемой. Затем нам нужно написать код для реализации соответствующих правил, запустить транзакцию и реализовать транзакцию.
Во-первых, мы можем проверить дела, связанные со springboot в Интернете, Это не более чем ленивый способ добавить аннотации непосредственно в сервисный метод.@Transactional
и использовать выше начального класса@EnableTransactionManagement
, чтобы транзакцию можно было запустить методом, указанным в проекте.
Но есть ли более ленивый способ? Должен быть, и предполагается, что он похож на проект Spring. Каков наш стандарт тестирования? Должно быть, в методе, соответствующем службе, произошло исключение, чтобы вызвать операцию отката. Другие принципы не нужно слишком подробно объяснять, просто сначала напишите код.
@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 не существует в базе данных, поэтому наше управление транзакциями выполнено успешно. Конкретный эффект не нужно изображать выше, каждый может увидеть его в своих соответствующих инструментах базы данных.