SpringBoot2-Глава 3: Управление транзакциями Springboot

задняя часть база данных GitHub Spring

В прошлой главе мы кратко представили реализацию, связанную с swagger, в конце концов, я только что опубликовал код напрямую, что действительно довольно просто, хахаха. В этой главе мы в основном вводим управление транзакциями в Springboot.

GitHub для этого проекта: https://github.com/pc859107393/Go2SpringBoot.git

Учащиеся, заинтересованные в общении со springboot для быстрой разработки, могут добавить следующую группу пингвинов.

行走的java全栈

Обзор управления транзакциями

В традиционном проекте Spring мы в основном выполняем управление транзакциями на сервисном уровне в классическом трехуровневом.Какова общая конфигурация? Конкретная реализация показана на рисунке 3.1.

图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 не существует в базе данных, поэтому наше управление транзакциями выполнено успешно. Конкретный эффект не нужно изображать выше, каждый может увидеть его в своих соответствующих инструментах базы данных.