Ваш код верен настолько, насколько это возможно: вы хотите использовать аннотацию Spring @Transactional для отдельных методов в своем классе обслуживания, чтобы получить гранулярность, которую вы ищете, вы правы, что вы хотите SUPPORTS для dontReadOrWrite (NOT_SUPPORTED приостановит существующую транзакцию, которая не купит вам ничего, основываясь на том, что вы описали, и потребует от вашего программного обеспечения тратить циклы, так что нет никакой выгоды), и вы правы, что хотите распространение по умолчанию поведение (ОБЯЗАТЕЛЬНО) для readSomething.
Но важно помнить о поведении транзакций в Spring: Spring реализует управление транзакциями, оборачивая ваш класс в прокси, который выполняет соответствующую настройку транзакции, вызывает ваш метод, а затем выполняет соответствующую транзакцию, когда управление прекращается. возвращается. И (что крайне важно), этот код управления транзакциями только вызывается при вызове метода на прокси-сервере, что не происходит, если writeSomething () напрямую вызывает dontReadOrWrite (), как в вашем первом пуле.
Если вам нужно другое поведение транзакций для метода, вызываемого другим методом, у вас есть два варианта, которые я знаю, если вы хотите продолжать использовать аннотации Spring @Transactional для управления транзакциями:
- Переместите вызываемый другим методом метод в другой класс обслуживания, к которому будет обращаться из исходного класса обслуживания через прокси Spring.
- Оставьте метод там, где он есть. Объявите переменную-член в вашем классе обслуживания того же типа, что и интерфейс вашего класса обслуживания, и сделайте ее @Autowired, которая даст вам ссылку на прокси-объект Spring вашего класса обслуживания. Затем, когда вы захотите вызвать свой метод с другим поведением транзакций, сделайте это для этой переменной-члена, а не напрямую, и код транзакции Spring будет запускаться так, как вы этого хотите.
Подход № 1 хорош, если эти два метода действительно не связаны между собой, потому что он решает вашу проблему, не сбивая с толку тех, кто заканчивает тем, что поддерживает ваш код, и нет никакого способа случайно забыть вызвать метод с поддержкой транзакций.
Подход №2, как правило, является лучшим вариантом, если предположить, что все ваши методы находятся в одном сервисе по какой-то причине и что вы не захотите их разделять. Но это сбивает с толку сопровождающего, который не понимает эту мелочь транзакций Spring, и вы должны помнить, чтобы вызывать его таким образом, в каждом месте, где вы его называете, так что есть цена. Я обычно готов заплатить эту цену, чтобы не раскалывать свои классы обслуживания неестественно, но, как всегда, это будет зависеть от вашей ситуации.