Сохранение сущностей в приватных методах - PullRequest
0 голосов
/ 01 марта 2019

У меня есть класс Ingestion, который предоставляет один метод ingest.Этот метод обрабатывает каждый раздел переданной формы (раздел 1, раздел 2 и т. Д. И т. Д.).

У меня есть закрытые методы для каждого раздела, сохраняющие сущность в процессе обработки.Мне известно, что @Transactional не влияет на частные методы, однако я не хочу показывать эти методы, но хотел бы использовать функциональность, предоставляемую @Transactional.

Я хочу убедиться, чтокаждый раздел завершается в своем собственном Transaction;Я мог бы сделать это с помощью «AspectJ» (как предлагали другие ответы SO) вместо Spring готовой реализации, но я стараюсь избегать из-за системных изменений, которые это может вызвать.

Любые мысли о другомподход?

Приведенный ниже псевдокод дает общее представление о структуре класса:

public Class Ingestion {
   // Autowired Repo's
   ...
   ...
   @Transactional
   public void ingest(Form form){
       this.processSection1(form);
       this.processSection2(form);
       this.processSection3(form);
   }

   @Transactional
   private void processSection1(Form form){
     // do specific section 1 logic
     section1Repo.save(form);
   }

   @Transactional
   private void processSection2(Form form){
     // do specific section2 logic
     section2Repo.save(form);
   }

   @Transactional
   private void processSection3(Form form){
     // do specific section3 logic
     section3Repo.save(form);
   }
}

=============================================================================== Это не повторяющийся вопрос, как отмечено в комментариях.Я знаю, @Transactional не работает на частных методах.Мой вопрос больше похож на то, как «как обойти эту проблему Spring AOP без использования AspectJ»

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Вы можете извлечь эти три метода обработки в другом классе, сделать их общедоступными, но установить уровень доступа конструктора класса на package-local (но не на private), поскольку Spring не может прокси-классы с закрытыми конструкторами), так что классы издругие пакеты могут получить доступ к этим методам только потому, что они не могут создать экземпляр своего класса.Это не скрывает эти методы полностью, но может соответствовать вашим потребностям.Этот трюк можно выполнить и с внутренним классом (обратите внимание, что он должен быть объявлен с локальным доступом к пакету).

Чтобы полностью скрыть эти методы, вы можете использовать декларативное управление транзакциями, введя TransactionTemplatebean и используя его execute метод в приватных методах.Эта функция поставляется из коробки.Подробнее здесь .

Также обратите внимание, что для создания новой транзакции при выполнении метода B из метода A, метод B должен быть объявлен @Transactional с типом распространенияREQUIRES_NEW.В противном случае любые вложенные методы будут вызываться в той же транзакции, которая была запущена начальным вызовом метода.

0 голосов
/ 01 марта 2019

Причина, по которой это не работает, состоит в том, что аннотации, подобные @Transactional, добавляют дополнительную функциональность, которая перехватывается прокси-объектом Spring, который обертывает фактический объект.Но когда вы вызываете приватный метод для объекта с ключевым словом this, вы идете прямо к реальному объекту и обходите прокси.

Один из способов решить эту проблему - @Autowire объект ви совершать транзакционные вызовы через эту переменную с автоматическим подключением.Таким образом, вы все равно можете получить доступ к закрытым методам, и вызов будет осуществляться через прокси-сервер, управляемый Spring, вместо чистого объекта.

...