Тут все довольно просто. У нас есть слой бизнес-логики, который имеет 3 интерфейса:
TransactionManager - собственно менеджер транзакций
OrderRepository - репозиторий заказов
PaymentRepository - репозиторий платежей
И, допустим, нам нужно транзакционно сделать следующий сценарий: "при получении платежа записать его в БД и изменить статус заказа на PAID" (пишу пример на Kotlin, надеюсь понятно)
transactionManager.inTransaction {
order.status = PAID
paymentRepository.save(payment)
orderRepository.save(order)
}
Собственно дальше - это уже вопрос реализации TransactionManager. Если мы имеем дело с простым случаем, таким как хранение данных в SQL Database, то его реализация должна быть понятна. Если более сложный случай - то распределенные транзакции, либо пустая реализация (транзакционность не поддерживается). Разумеется, при инжекции зависимостей в модуль бизнес-логики реализация менеджера транзакций должна соответствовать реализации репозиториев (мало толку будет если менеджер транзакций реализует транзакционность в БД, а репозитории - хранение в файлах). Но это уже слегка другой разговор, тут на помощь приходят фабрики и подобные шаблоны.