JpaRepository.getOne путаница

Я работаю над большим проектом, который использует фреймворк Spring, где у меня есть такая услуга:

  @Component
  public class ExampleService{

       @Autowired
       ChildOfJpaRepository childOfJpaRepository;

       public void fetchAndSet(ExampleParentEntity exampleParentEntity,Long id){
          exampleParentEntity.setChildEntity(childOfJpaRepository.getOne(id));
       }
  }

ChildOfJpaRepository - это интерфейс репозитория, расширяющий JpaRepository (из пакета org.springframework.data.jpa.repository). ExampleParentEntity - это просто некоторая сущность БД, у которой есть поле ExampleChildEntity и сеттер. Когда я звоню childOfJpaRepository.getOne(id), я ожидаю получить прокси ExampleChildEntity. Однако оказалось, что мой childOfJpaRepository упакован в JdkDynamicAopProxy. Когда выполняется метод getOne, он вызывает TransactionInterceptor и через некоторое время создает транзакцию. Вот полная трассировка стека того, что происходит после выполнения getOne (это не трассировка стека ошибок, а просто то, что происходит после запуска getOne):

com.sun.proxy.$Proxy1092.getOne() org.springframework.aop.framework.JdkDynamicAopProxy.invoke() org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke() org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke() org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
org.springframework.transaction.interceptor.TransactionInterceptor.invoke() org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction() org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary() org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning()
org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation()

Моя проблема в том, что поскольку создается транзакция, вместо получения прокси-сервера ExampleChildEntity, я фактически получаю ExampleChildEntity (и мне нужен прокси). Из моих анализов кажется, что у меня проблема с конфигурациями аспектно-ориентированного программирования. Как я могу отключить эту упаковку JdkDynamicAopProxy или как изменить ее поведение (я не хочу, чтобы она вызывала создание транзакции)?

Может ли ChildOfJpaRepository переопределять поведение getOne?

Zeromus 13.04.2018 15:13

Вот реализация getOne (): github.com/spring-projects/spring-data-jpa/blob/…. Поэтому, если вы не переопределите его, все, что он делает, это вызывает getReference (), и поэтому нет причин, по которым он ведет себя иначе.

JB Nizet 13.04.2018 15:14

@Zeromus, к сожалению, нет

pokemzok 13.04.2018 15:14

@JBNizet Я обновил свой вопрос.

pokemzok 16.04.2018 13:31

Почему вы удалили фактическое сообщение об ошибке из трассировки стека? А где твой MCVE? Трассировка стека ясно показывает, что происходит некоторая проблема аспекта транзакции, что противоречит вашему собственному утверждению о том, что в вашем коде такой вещи нет. Без MCVE, вероятно, никто не сможет вам помочь.

kriegaex 17.04.2018 08:14

@kriegaex - я наблюдаю эту трассировку стека в jvisualvm, поэтому сообщения об ошибке нет. Это просто наблюдение за тем, как выполняется код. Я также только заявляю, что в моем коде «похоже, нет ни аннотаций транзакций в иерархии вызовов fetchAndSet, ни каких-либо конфигураций транзакций, кроме управляемых аннотациями». Вы должны понимать, что я явно новичок в АОП и мало что знал об этом до того, как возникла проблема, и потребовались часы отладки.

pokemzok 17.04.2018 09:34

И вы должны понимать, что профессиональные разработчики, проводящие свободное время для помощи другим, любят давать советы, основанные на фактах, а не на чистых предположениях. Так что не имеет значения, новичок вы в АОП или нет. Предоставьте воспроизводимое описание проблемы или, при всем уважении, решите свою проблему в одиночку. Если вы можете наблюдать трассировку стека через VisualVM, возможно, вы также можете увидеть соответствующую ошибку где-нибудь на консоли сервера или в файлах журнала. Если ошибок нет, то в чем проблема? MCVE покажет, что происходит, и вместо этого вы можете сказать, что ожидаете.

kriegaex 17.04.2018 09:41

@kriegaex - Справедливый момент. Я отредактировал свой вопрос. Надеюсь, теперь стало более ясно.

pokemzok 17.04.2018 10:15

Конечно, ваш репозиторий является прокси-сервером, поскольку именно так он реализуется во время выполнения. Поэтому нет, вы не можете отключить это, если не хотите удалить Spring Data JPA. Я также сомневаюсь, что проблема на самом деле связана с вызовом getOne (вы не разместили полную трассировку стека, просто фрагмент).

M. Deinum 17.04.2018 10:28
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
9
389
0

Другие вопросы по теме